Repository navigation
Conversation
…olden Gate and iOS27 https://bugs.webkit.org/show_bug.cgi?id=322747 rdar://186011516 Reviewed by Jonathan Bedard. Migrate EWS workers from macOS Tahoe 26.6 to macOS Golden Gate 27.2. iOS-26-Build-EWS, macOS-Safer-CPP-Checks-EWS, and Apple-iOS-26-Safer-CPP-Checks-EWS stay on Tahoe. Unpark 14 previously-disconnected bots and raise pop counts on backlogged queues. * Tools/CISupport/ews-build/config-template.yaml: * Tools/CISupport/ews-build/factories_unittest.py: Canonical link: https://commits.webkit.org/325874@main
…flaky https://bugs.webkit.org/show_bug.cgi?id=330217 rdar://191853637 Reviewed by Qianlang Chen. InspectorTest.TimelineEvent.captureTimelineWithScript() stopped capturing as soon as the first matching record arrived. A screenshot does not come from the evaluated script, so it can arrive before every instrument has reported that it started. If such a start arrives while capturing stops, TimelineManager.capturingStarted() makes capturing active again. Then the helper evaluated the script a second time, and the test logged "Evaluating..." and "Stopping Capture..." twice. Stop capturing only when the reply to the evaluation has also arrived. The frontend sends the evaluation after it starts every instrument, and the backend replies after the events of those starts, so no start can arrive late. Canonical link: https://commits.webkit.org/325875@main
… macOS https://bugs.webkit.org/show_bug.cgi?id=330293 rdar://191909106 Reviewed by Tim Horton and Abrar Rahman Protyasha. Re-land of 325344@main. Tests: Tools/TestWebKitAPI/Tests/WebKit/WebPage/WebViewTests.swift fast/scrolling/mac/scroll-to-document-edge-animation.html fast/scrolling/mac/scroll-to-document-edge-during-momentum.html fast/scrolling/mac/scroll-to-document-edge-interrupted-by-page-scroll.html fast/scrolling/mac/scroll-to-document-edge-interrupted-by-wheel-over-nested-scroller.html fast/scrolling/mac/scroll-to-document-edge-interrupted-by-wheel.html fast/scrolling/mac/scroll-to-document-edge-interrupted-in-scroll-snap-container.html fast/scrolling/mac/scroll-to-document-edge-interrupted-on-main-thread.html fast/scrolling/mac/scroll-to-document-edge-resets-inline-axis.html fast/scrolling/mac/scroll-to-document-edge-reversal.html * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-animation-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-animation.html: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-during-momentum-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-during-momentum.html: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-by-page-scroll-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-by-page-scroll.html: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-by-wheel-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-by-wheel-over-nested-scroller-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-by-wheel-over-nested-scroller.html: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-by-wheel.html: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-in-scroll-snap-container-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-in-scroll-snap-container.html: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-on-main-thread-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-interrupted-on-main-thread.html: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-resets-inline-axis-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-resets-inline-axis.html: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-reversal-expected.txt: Added. * LayoutTests/fast/scrolling/mac/scroll-to-document-edge-reversal.html: Added. * Source/WebCore/page/scrolling/AsyncScrollingCoordinator.cpp: (WebCore::AsyncScrollingCoordinator::requestScrollToPosition): * Source/WebCore/page/scrolling/ScrollingCoordinatorTypes.cpp: (WebCore::operator<<): * Source/WebCore/page/scrolling/ScrollingCoordinatorTypes.h: (WebCore::RequestedScrollData::operator== const): * Source/WebCore/page/scrolling/ScrollingStateScrollingNode.cpp: (WebCore::ScrollingStateScrollingNode::dumpProperties const): * Source/WebCore/page/scrolling/ScrollingTree.cpp: (WebCore::ScrollingTree::stopSpringAnimationsForWheelEvent): * Source/WebCore/page/scrolling/ScrollingTree.h: * Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.cpp: (WebCore::ScrollingTreeScrollingNode::startAnimatedScrollToPosition): (WebCore::ScrollingTreeScrollingNode::stopSpringAnimation): (WebCore::ScrollingTreeScrollingNode::handleScrollPositionRequest): * Source/WebCore/page/scrolling/ScrollingTreeScrollingNode.h: * Source/WebCore/page/scrolling/ScrollingTreeScrollingNodeDelegate.h: (WebCore::ScrollingTreeScrollingNodeDelegate::stopSpringAnimation): * Source/WebCore/page/scrolling/ThreadedScrollingTree.cpp: (WebCore::ThreadedScrollingTree::didCommitTreeOnScrollingThread): * Source/WebCore/page/scrolling/ThreadedScrollingTreeScrollingNodeDelegate.cpp: (WebCore::ThreadedScrollingTreeScrollingNodeDelegate::startAnimatedScrollToPosition): (WebCore::ThreadedScrollingTreeScrollingNodeDelegate::stopSpringAnimation): * Source/WebCore/page/scrolling/ThreadedScrollingTreeScrollingNodeDelegate.h: * Source/WebCore/page/scrolling/mac/ScrollingTreeScrollingNodeDelegateMac.mm: (WebCore::ScrollingTreeScrollingNodeDelegateMac::handleWheelEvent): * Source/WebCore/platform/KeyboardScroll.h: * Source/WebCore/platform/KeyboardScrollingAnimator.cpp: (WebCore::KeyboardScrollingAnimator::beginKeyboardScrollGesture): * Source/WebCore/platform/ScrollAnimationSmooth.cpp: (WebCore::ScrollAnimationSmooth::startAnimatedScrollToDestination): (WebCore::ScrollAnimationSmooth::retargetActiveAnimation): (WebCore::ScrollAnimationSmooth::durationFromDistance const): (WebCore::ScrollAnimationSmooth::springProgress): (WebCore::ScrollAnimationSmooth::animateScroll): (WebCore::ScrollAnimationSmooth::debugDescription const): * Source/WebCore/platform/ScrollAnimationSmooth.h: * Source/WebCore/platform/ScrollAnimator.cpp: (WebCore::ScrollAnimator::singleAxisScroll): (WebCore::ScrollAnimator::scrollToPositionWithAnimation): (WebCore::ScrollAnimator::retargetRunningAnimation): * Source/WebCore/platform/ScrollAnimator.h: * Source/WebCore/platform/ScrollTypes.cpp: (WebCore::operator<<): * Source/WebCore/platform/ScrollTypes.h: (WebCore::documentEdgeScrollAnimationCurve): * Source/WebCore/platform/ScrollableArea.cpp: (WebCore::ScrollableArea::scroll): (WebCore::ScrollableArea::scrollToPositionWithAnimation): (WebCore::ScrollableArea::resnapAfterLayout): * Source/WebCore/platform/ScrollingEffectsController.cpp: (WebCore::ScrollingEffectsController::startAnimatedScrollToDestination): (WebCore::ScrollingEffectsController::retargetAnimatedScroll): (WebCore::ScrollingEffectsController::retargetAnimatedScrollBy): (WebCore::ScrollingEffectsController::animatedScrollDestinationOffset const): (WebCore::ScrollingEffectsController::isSpringAnimationRunning const): (WebCore::ScrollingEffectsController::stopSpringAnimation): * Source/WebCore/platform/ScrollingEffectsController.h: * Source/WebCore/platform/mac/ScrollAnimatorMac.mm: (WebCore::ScrollAnimatorMac::handleWheelEvent): * Source/WebCore/platform/mac/ScrollingEffectsController.mm: (WebCore::ScrollingEffectsController::handleWheelEventDuringSpringAnimation): * Source/WebCore/rendering/RenderLayerScrollableArea.cpp: (WebCore::RenderLayerScrollableArea::scrollToOffset): * Source/WebKit/Shared/WebCoreArgumentCoders.serialization.in: * Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.h: * Source/WebKit/UIProcess/RemoteLayerTree/ios/ScrollingTreeScrollingNodeDelegateIOS.mm: (WebKit::ScrollingTreeScrollingNodeDelegateIOS::startAnimatedScrollToPosition): * Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteLayerTreeEventDispatcher.mm: (WebKit::RemoteLayerTreeEventDispatcher::scrollingThreadHandleWheelEvent): * Source/WebKit/UIProcess/RemoteLayerTree/mac/RemoteScrollingTreeMac.mm: (WebKit::RemoteScrollingTreeMac::startPendingScrollAnimations): * Source/WebKit/UIProcess/ios/WKKeyboardScrollingAnimator.mm: (-[WKKeyboardScrollingAnimator beginWithEvent:]): * Source/WebKit/WebProcess/WebPage/WebPage.cpp: (WebKit::WebPage::scrollToEdge): * Tools/TestWebKitAPI/Helpers/cocoa/SwiftUI+Extras.swift: * Tools/TestWebKitAPI/Tests/WebKit/WebPage/WebViewTests.swift: (ScrollPositionTestView.body): (WebViewTests.animatedScrollToEdgeUsesSpring): Canonical link: https://commits.webkit.org/325876@main
…olden Gate and iOS27 https://bugs.webkit.org/show_bug.cgi?id=322747 rdar://186011516 Reviewed by Jonathan Bedard. * Tools/CISupport/ews-build/config-template.yaml: Follow up fix to change the OS version for AWS machines. Canonical link: https://commits.webkit.org/325877@main
https://bugs.webkit.org/show_bug.cgi?id=329167 rdar://191149960 Reviewed by Richard Robinson. A Swift IPC receiver today gets its arguments, and returns its reply, as C++ types, so every handler pays the cost of Swift/C++ interop even when it never hands the values back to C++. A receiver can now opt in to pure Swift types instead: the receiver attribute SwiftTypes makes it the default for all of its messages, and the message attributes SwiftTypes and CxxTypes opt individual messages in or out. The wire format is unchanged, so senders and the C++ receiver built when SwiftReceiverBuildEnabledBy is off are unaffected. For a message that takes Swift types, C++ no longer decodes the arguments. It lends generated Swift an IPC::SwiftDecoder whose primitive decoders are the C++ ones, so alignment and validation of primitives stay in one place. Generated Swift composes the primitives into Swift values before dispatch, and returns false if they are malformed, in which case C++ marks the message invalid as it would for a C++ decoding failure. Generated Swift encodes the handler's return value into an IPC::SwiftReplyEncoder, which owns the real reply Encoder and sends the usual default reply if the handler throws InvalidMessage. SendableClosureCaptures diagnostics become errors, because otherwise Swift lets concurrently executing code write to an inout parameter, such as the lent IPC::SwiftDecoder. The Swift types come from the same .serialization.in descriptions as the C++ coders: generate-serializers.py now writes GeneratedSerializers.swift, holding a Swift struct, enum, OptionSet or Variant enum, with its IPCCoder conformance, in the IPCTypes namespace for every type marked [Swift], and an IPCObjectIdentifier for every ObjectIdentifier. WTF::String becomes String?, Vector becomes Array, std::optional, Markable and RefPtr become Optional, and Ref<T> becomes T. Decoding rejects whatever the C++ coders reject: unknown enum values and OptionSet bits, out of range Variant indices and invalid identifiers. The generators reject what they cannot represent faithfully, such as C++ validators, CreateUsing, stream receivers and conditional members and values, and C++ static_asserts check the enum values and widths that the Swift side assumes. Generated decoding names each type through IPCTypes.CxxName, so a message whose C++ type has no exact Swift counterpart fails to compile rather than decoding as another type. IPCTesterReceiver now has a message that takes C++ types in Swift and messages that take Swift types, covering structs, enums, OptionSets, Variants, identifiers, Ref and RefPtr, strings of every encoding, and async, sync, no and multiple value replies. The C++ IPCTesterReceiver gives identical replies when Swift is not enabled. Alternatives considered: * Use the Swift Codable protocol, or some equivalent custom protocol, instead of .serialization.in. This makes for nicer code, but loses the "central auditability" purpose of the .in files which is critical for the defensibility of this IPC surface. In future, we might consider options like this. Future work: * Extend to stream connections. * Allow validators, on messages and on members of [Swift] types. Tests: Tools/TestWebKitAPI/Tests/WTF/NonEscapableBorrow.cpp ipc/swift-receiver-swift-types-malformed.html ipc/swift-receiver-swift-types.html * Broaden the "if" conditions so they're not tied to the two current uses of Swift, the back forward list and IPC testing. Tests: Source/WebKit/Scripts/webkit/generate_serializers_unittest.py Source/WebKit/Scripts/webkit/messages_unittest.py Source/WebKit/Scripts/webkit/model_unittest.py Source/WebKit/Scripts/webkit/parser_unittest.py Source/WebKit/Scripts/webkit/swift_types_unittest.py Tools/TestWebKitAPI/Tests/WTF/NonEscapableBorrow.cpp ipc/swift-receiver-swift-types-malformed.html ipc/swift-receiver-swift-types.html * Configurations/CommonBase.xcconfig: * LayoutTests/ipc/swift-receiver-swift-types-expected.txt: Added. * LayoutTests/ipc/swift-receiver-swift-types-malformed-expected.txt: Added. * LayoutTests/ipc/swift-receiver-swift-types-malformed.html: Added. * LayoutTests/ipc/swift-receiver-swift-types.html: Added. * Source/WTF/WTF.xcodeproj/project.pbxproj: * Source/WTF/wtf/CMakeLists.txt: * Source/WTF/wtf/NonEscapableBorrow.h: Added. (WTF::NonEscapableBorrowLender::NonEscapableBorrowLender): (WTF::NonEscapableBorrowLender::~NonEscapableBorrowLender): (WTF::NonEscapableBorrow::NonEscapableBorrow): (WTF::NonEscapableBorrow::borrowed const): * Source/WebKit/CMakeLists.txt: * Source/WebKit/DerivedSources-input.xcfilelist: * Source/WebKit/DerivedSources-output.xcfilelist: * Source/WebKit/DerivedSources.make: * Source/WebKit/Modules/Internal/module.modulemap: * Source/WebKit/Platform/IPC/Decoder.h: * Source/WebKit/Platform/IPC/HandleMessage.h: (IPC::markSwiftArgumentsInvalid): (IPC::encodeDefaultSwiftReply): (IPC::handleSwiftMessage): (IPC::handleSwiftMessageAsync): (IPC::handleSwiftMessageSynchronous): * Source/WebKit/Platform/IPC/SwiftCoding.h: Added. (IPC::SwiftDecoder::decodeBool): (IPC::SwiftDecoder::decodeUInt8): (IPC::SwiftDecoder::decodeUInt16): (IPC::SwiftDecoder::decodeUInt32): (IPC::SwiftDecoder::decodeUInt64): (IPC::SwiftDecoder::decodeInt8): (IPC::SwiftDecoder::decodeInt16): (IPC::SwiftDecoder::decodeInt32): (IPC::SwiftDecoder::decodeInt64): (IPC::SwiftDecoder::decodeFloat): (IPC::SwiftDecoder::decodeDouble): (IPC::SwiftDecoder::remainingByteCount const): (IPC::SwiftDecoder::isValid const): (IPC::SwiftDecoder::markInvalid): (IPC::SwiftDecoder::SwiftDecoder): (IPC::SwiftDecoder::decode): (IPC::SwiftDecoder::beginArray): * Source/WebKit/Platform/IPC/SwiftCoding.swift: Added. (IPCCoder.decode(from:)): (IPCCoder.encode(_:to:)): (Bool.decode(from:)): (Bool.encode(_:to:)): (UInt8.decode(from:)): (UInt8.encode(_:to:)): (UInt16.decode(from:)): (UInt16.encode(_:to:)): (UInt32.decode(from:)): (UInt32.encode(_:to:)): (UInt64.decode(from:)): (UInt64.encode(_:to:)): (Int8.decode(from:)): (Int8.encode(_:to:)): (Int16.decode(from:)): (Int16.encode(_:to:)): (Int32.decode(from:)): (Int32.encode(_:to:)): (Int64.decode(from:)): (Int64.encode(_:to:)): (Float.decode(from:)): (Float.encode(_:to:)): (Double.decode(from:)): (Double.encode(_:to:)): (IPCObjectIdentifier.decode(from:)): (IPCObjectIdentifier.encode(_:to:)): (StdOptional.decode(from:)): (StdOptional.encode(_:to:)): (Markable.decode(from:)): (Markable.encode(_:to:)): (Vector.decode(from:)): (Vector.encode(_:to:)): (WTFString.decode(from:)): (WTFString.encode(_:to:)): (IPCObjectIdentifier.value): (IPCObjectIdentifier.rawValue): * Source/WebKit/Scripts/generate-serializers.py: (matches_bundle): (SerializedType.__init__): (SerializedEnum.attribute_list): (SerializedEnum): (SerializedEnum.is_swift): (attribute_list): (UsingStatement.__init__): (UsingStatement): (UsingStatement.is_swift): (generate_impl): (parse_serialized_types): (SwiftTypeName): (SwiftTypeName.__init__): (SwiftCxxName): (SwiftCxxName.__init__): (SwiftMember): (SwiftMember.__init__): (swift_identifier): (swift_lower_camel_case): (swift_condition): (swift_qualified_name): (swift_identifiers): (swift_type_names): (swift_type_names.add): (check_swift_type_references): (swift_type_and_coder): (check_swift_type_attributes): (swift_members): (swift_members.is): (check_swift_names_are_unique): (swift_conditional_lines): (swift_coder_conformance): (swift_guarded): (generate_swift_struct): (generate_swift_enum): (swift_variant_case_name): (generate_swift_variant): (generate_swift_identifiers): (generate_swift_cxx_names): (swift_line_comments): (generate_swift): (swift_enum_value_assertions): (main): * Source/WebKit/Scripts/webkit/generate_serializers_unittest.py: Added. (generate_swift): (enum_value_assertions): (GeneratedSwiftTest): (GeneratedSwiftTest.test_generated_file): (GeneratedSwiftTest.test_lower_camel_case): (GeneratedSwiftTest.test_variant_case_names): (GeneratedSwiftTest.test_no_swift_types): (WebKit): (WebCore): (WTF): (ProcessQualified): (Pair): (GeneratedSwiftTest.test_cxx_names): * Source/WebKit/Scripts/webkit/messages.py: (types_that_cannot_be_forward_declared): (message_to_completion_handler_using_declaration): (messages_with_completion_handlers): (messages_with_distinct_reply_types): (generate_messages_header.append_completion_handler_types_for_swift): (swift_type_aliases): (swift_reply_completion_call): (swift_reply_encoding_statements): (generates_swift_trampoline): (swift_types_dispatch_function): (async_message_statement.append_with_dispatch_function_args): (async_message_statement): (sync_message_statement.append_call_with_target_name): (sync_message_statement): (headers_for_type): (generate_message_handler.append_complete_with_default_reply_definitions): (generate_swift_message_handler): * Source/WebKit/Scripts/webkit/messages_unittest.py: * Source/WebKit/Scripts/webkit/model.py: (MessageReceiver.__init__): (MessageReceiver.is_swift_receiver): (MessageReceiver): (MessageReceiver.takes_swift_types): (MessageReceiver.enforce_swift_types_constraints): (MessageReceiver._enforce_swift_types_constraints_for_message): (MessageReceiver._enforce_swift_types_constraints_for_message.unsupported): (check_global_model_inputs): * Source/WebKit/Scripts/webkit/model_unittest.py: (ModelCheckTest.test_mismatch_message_attribute_swift_types): (ModelCheckTest): (ModelCheckTest.test_async_reply_messages_do_not_take_swift_types): * Source/WebKit/Scripts/webkit/parser.py: (parse): * Source/WebKit/Scripts/webkit/parser_unittest.py: (parse_swift_receiver): (UnsupportedPrecompilerDirectiveTest): Deleted. (UnsupportedPrecompilerDirectiveTest.test_error_at_else): Deleted. (UnsupportedPrecompilerDirectiveTest.test_error_at_elif): Deleted. * Source/WebKit/Scripts/webkit/swift_types.py: Added. (UnmappableSwiftType): (UnmappableSwiftCondition): (strip_cpp_type_decorations): (split_template_arguments): (swift_cxx_name): (swift_type_and_coder): (swift_coder): (swift_condition): (swift_condition.replace): * Source/WebKit/Scripts/webkit/swift_types_unittest.py: Added. (SwiftTypeAndCoderTest): (SwiftTypeAndCoderTest.test_types): (SwiftTypeAndCoderTest.test_coders_without_cxx_names): (SwiftTypeAndCoderTest.test_unmappable_types): (SwiftTypeAndCoderTest.test_cxx_name): (SwiftTypeAndCoderTest.test_helpers): (SwiftConditionTest): (SwiftConditionTest.test_conditions): (SwiftConditionTest.test_unavailable_macros): (SwiftConditionTest.test_unsupported_expressions): * Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.cpp: (IPC::ArgumentCoder<WTF::ObjectIdentifier<WebCore::FrameIdentifierType>>::encode): (IPC::ArgumentCoder<WTF::ObjectIdentifier<WebCore::FrameIdentifierType>>::decode): (IPC::ArgumentCoder<WTF::ObjectIdentifier<WebKit::NotAnIdentifierTag>>::encode): (IPC::ArgumentCoder<WTF::ObjectIdentifier<WebKit::NotAnIdentifierTag>>::decode): (IPC::ArgumentCoder<WTF::AtomicObjectIdentifier<WebKit::SwiftAtomicTestIdentifierType>>::encode): (IPC::ArgumentCoder<WTF::AtomicObjectIdentifier<WebKit::SwiftAtomicTestIdentifierType>>::decode): (IPC::ArgumentCoder<Namespace::SwiftInner>::encode): (IPC::ArgumentCoder<Namespace::SwiftInner>::decode): (IPC::ArgumentCoder<Namespace::SwiftStruct>::encode): (IPC::ArgumentCoder<Namespace::SwiftStruct>::decode): (IPC::ArgumentCoder<Namespace::SwiftNode>::encode): (IPC::ArgumentCoder<Namespace::SwiftNode>::decode): (IPC::ArgumentCoder<Namespace::SwiftLeaf>::encode): (IPC::ArgumentCoder<Namespace::SwiftLeaf>::decode): (IPC::ArgumentCoder<Namespace::SwiftBase>::encode): (IPC::ArgumentCoder<Namespace::SwiftBase>::decode): (IPC::ArgumentCoder<Namespace::SwiftDerived>::encode): (IPC::ArgumentCoder<Namespace::SwiftDerived>::decode): (WTF::isValidEnum<Namespace::SwiftEnum>): (WTF::isValidEnum<Namespace::SwiftBoolEnum>): (WTF::isValidOptionSet<Namespace::SwiftOptionSet>): * Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.h: * Source/WebKit/Scripts/webkit/tests/GeneratedSerializers.swift: Added. (IPCTypes.decode(from:)): (IPCTypes.encode(_:to:)): (SwiftInner.value): (SwiftInner.label): (SwiftStruct.flag): (SwiftStruct.name): (SwiftStruct.numbers): (SwiftStruct.strings): (SwiftStruct.optionalDouble): (SwiftStruct.markableFrameID): (SwiftStruct.frameID): (SwiftStruct.atomicID): (SwiftStruct.inner): (SwiftStruct.optionalInner): (SwiftStruct.enumValue): (SwiftStruct.boolEnum): (SwiftStruct.options): (SwiftStruct.variant): (SwiftStruct.accessor): (SwiftNode.name): (SwiftNode.children): (SwiftNode.optionalLeaf): (SwiftNode.leaf): (SwiftLeaf.value): (SwiftDerived.baseValue): (SwiftDerived.derivedValue): * Source/WebKit/Scripts/webkit/tests/Makefile: * Source/WebKit/Scripts/webkit/tests/MessageArgumentDescriptions.cpp: (IPC::jsValueForArguments): (IPC::jsValueForReplyArguments): (IPC::messageArgumentDescriptions): (IPC::messageReplyArgumentDescriptions): * Source/WebKit/Scripts/webkit/tests/MessageNames.cpp: * Source/WebKit/Scripts/webkit/tests/MessageNames.h: * Source/WebKit/Scripts/webkit/tests/SerializedTypeInfo.cpp: (WebKit::allSerializedTypes): (WebKit::allSerializedEnums): * Source/WebKit/Scripts/webkit/tests/TestSerializedType.serialization.in: * Source/WebKit/Scripts/webkit/tests/TestWithSwiftTypes.messages.in: Copied from Source/WebKit/Shared/IPCTesterReceiver.messages.in. * Source/WebKit/Scripts/webkit/tests/TestWithSwiftTypesMessageReceiver.cpp: Added. (WebKit::TestWithSwiftTypesMessageForwarder::didReceiveMessage): (WebKit::TestWithSwiftTypesMessageForwarder::didReceiveSyncMessage): (WebKit::makeTestWithSwiftTypesWeakRefUniquePtr): (WebKit::TestWithSwiftTypesMessageForwarder::TestWithSwiftTypesMessageForwarder): (WebKit::TestWithSwiftTypesMessageForwarder::getMessageTarget): (WebKit::TestWithSwiftTypesMessageForwarder::~TestWithSwiftTypesMessageForwarder): (CompletionHandlers::TestWithSwiftTypes::completeWithDefaultReply): (CompletionHandlers::TestWithSwiftTypes::complete): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithoutReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithoutParameters>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithReply>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypes_MessageWithReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithMultipleReplies>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypes_MessageWithMultipleReplies>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithEmptyReply>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypes_MessageWithEmptyReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithRefs>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypes_MessageWithRefs>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_SynchronousMessage>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypes_SynchronousMessage>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_SynchronousMessageWithoutParameters>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypes_SynchronousMessageWithoutParameters>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithCxxTypes>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypes_MessageWithCxxTypes>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithReplyReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithMultipleRepliesReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithEmptyReplyReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithRefsReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypes_MessageWithCxxTypesReply>): * Source/WebKit/Scripts/webkit/tests/TestWithSwiftTypesMessageReceiver.swift: Added. (TestWithSwiftTypesWeakRef.target): (TestWithSwiftTypesWeakRef.getMessageTarget): (MessageWithoutReplyInvocation.run): (MessageWithoutParametersInvocation.run): (MessageWithReplyInvocation.run): (MessageWithMultipleRepliesInvocation.run): (MessageWithEmptyReplyInvocation.run): (MessageWithRefsInvocation.run): (SynchronousMessageInvocation.run): (SynchronousMessageWithoutParametersInvocation.run): (MessageWithCxxTypesInvocation.run): (WebKit.create(_:)): * Source/WebKit/Scripts/webkit/tests/TestWithSwiftTypesMessages.h: Added. (Messages::TestWithSwiftTypes::messageReceiverName): (Messages::TestWithSwiftTypes::MessageWithoutReply::name): (Messages::TestWithSwiftTypes::MessageWithoutReply::MessageWithoutReply): (Messages::TestWithSwiftTypes::MessageWithoutReply::encode): (Messages::TestWithSwiftTypes::MessageWithoutParameters::name): (Messages::TestWithSwiftTypes::MessageWithoutParameters::MessageWithoutParameters): (Messages::TestWithSwiftTypes::MessageWithoutParameters::encode): (Messages::TestWithSwiftTypes::MessageWithReply::name): (Messages::TestWithSwiftTypes::MessageWithReply::asyncMessageReplyName): (Messages::TestWithSwiftTypes::MessageWithReply::MessageWithReply): (Messages::TestWithSwiftTypes::MessageWithReply::encode): (Messages::TestWithSwiftTypes::MessageWithMultipleReplies::name): (Messages::TestWithSwiftTypes::MessageWithMultipleReplies::asyncMessageReplyName): (Messages::TestWithSwiftTypes::MessageWithMultipleReplies::MessageWithMultipleReplies): (Messages::TestWithSwiftTypes::MessageWithMultipleReplies::encode): (Messages::TestWithSwiftTypes::MessageWithEmptyReply::name): (Messages::TestWithSwiftTypes::MessageWithEmptyReply::asyncMessageReplyName): (Messages::TestWithSwiftTypes::MessageWithEmptyReply::MessageWithEmptyReply): (Messages::TestWithSwiftTypes::MessageWithEmptyReply::encode): (Messages::TestWithSwiftTypes::MessageWithRefs::name): (Messages::TestWithSwiftTypes::MessageWithRefs::asyncMessageReplyName): (Messages::TestWithSwiftTypes::MessageWithRefs::MessageWithRefs): (Messages::TestWithSwiftTypes::MessageWithRefs::encode): (Messages::TestWithSwiftTypes::SynchronousMessage::name): (Messages::TestWithSwiftTypes::SynchronousMessage::SynchronousMessage): (Messages::TestWithSwiftTypes::SynchronousMessage::encode): (Messages::TestWithSwiftTypes::SynchronousMessageWithoutParameters::name): (Messages::TestWithSwiftTypes::SynchronousMessageWithoutParameters::SynchronousMessageWithoutParameters): (Messages::TestWithSwiftTypes::SynchronousMessageWithoutParameters::encode): (Messages::TestWithSwiftTypes::MessageWithCxxTypes::name): (Messages::TestWithSwiftTypes::MessageWithCxxTypes::asyncMessageReplyName): (Messages::TestWithSwiftTypes::MessageWithCxxTypes::MessageWithCxxTypes): (Messages::TestWithSwiftTypes::MessageWithCxxTypes::encode): (Messages::TestWithSwiftTypes::MessageWithReplyReply::name): (Messages::TestWithSwiftTypes::MessageWithReplyReply::MessageWithReplyReply): (Messages::TestWithSwiftTypes::MessageWithReplyReply::encode): (Messages::TestWithSwiftTypes::MessageWithMultipleRepliesReply::name): (Messages::TestWithSwiftTypes::MessageWithMultipleRepliesReply::MessageWithMultipleRepliesReply): (Messages::TestWithSwiftTypes::MessageWithMultipleRepliesReply::encode): (Messages::TestWithSwiftTypes::MessageWithEmptyReplyReply::name): (Messages::TestWithSwiftTypes::MessageWithEmptyReplyReply::MessageWithEmptyReplyReply): (Messages::TestWithSwiftTypes::MessageWithEmptyReplyReply::encode): (Messages::TestWithSwiftTypes::MessageWithRefsReply::name): (Messages::TestWithSwiftTypes::MessageWithRefsReply::MessageWithRefsReply): (Messages::TestWithSwiftTypes::MessageWithRefsReply::encode): (Messages::TestWithSwiftTypes::MessageWithCxxTypesReply::name): (Messages::TestWithSwiftTypes::MessageWithCxxTypesReply::MessageWithCxxTypesReply): (Messages::TestWithSwiftTypes::MessageWithCxxTypesReply::encode): * Source/WebKit/Scripts/webkit/tests/TestWithSwiftTypesOptIn.messages.in: Copied from Source/WebKit/Shared/IPCTesterReceiver.messages.in. * Source/WebKit/Scripts/webkit/tests/TestWithSwiftTypesOptInMessageReceiver.cpp: Added. (WebKit::TestWithSwiftTypesOptIn::didReceiveMessage): (WebKit::TestWithSwiftTypesOptIn::didReceiveSyncMessage): (WebKit::makeTestWithSwiftTypesOptInWeakRefUniquePtr): (WebKit::TestWithSwiftTypesOptInMessageForwarder::TestWithSwiftTypesOptInMessageForwarder): (WebKit::TestWithSwiftTypesOptInMessageForwarder::getMessageTarget): (WebKit::TestWithSwiftTypesOptInMessageForwarder::~TestWithSwiftTypesOptInMessageForwarder): (CompletionHandlers::TestWithSwiftTypesOptIn::completeWithDefaultReply): (CompletionHandlers::TestWithSwiftTypesOptIn::complete): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypesOptIn_CxxTypedMessage>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypesOptIn_CxxTypedMessage>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypesOptIn_SwiftTypedMessage>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypesOptIn_SwiftTypedMessage>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypesOptIn_SwiftTypedMessageWithoutReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypesOptIn_SwiftTypedSynchronousMessage>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypesOptIn_SwiftTypedSynchronousMessage>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypesOptIn_CxxTypedSynchronousMessage>): (IPC::jsValueForDecodedMessageReply<MessageName::TestWithSwiftTypesOptIn_CxxTypedSynchronousMessage>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypesOptIn_CxxTypedMessageReply>): (IPC::jsValueForDecodedMessage<MessageName::TestWithSwiftTypesOptIn_SwiftTypedMessageReply>): * Source/WebKit/Scripts/webkit/tests/TestWithSwiftTypesOptInMessageReceiver.swift: Added. (TestWithSwiftTypesOptInWeakRef.target): (TestWithSwiftTypesOptInWeakRef.getMessageTarget): (CxxTypedMessageInvocation.run): (SwiftTypedMessageInvocation.run): (SwiftTypedMessageWithoutReplyInvocation.run): (SwiftTypedSynchronousMessageInvocation.run): (CxxTypedSynchronousMessageInvocation.run): (WebKit.create(_:)): * Source/WebKit/Scripts/webkit/tests/TestWithSwiftTypesOptInMessages.h: Added. (Messages::TestWithSwiftTypesOptIn::messageReceiverName): (Messages::TestWithSwiftTypesOptIn::CxxTypedMessage::name): (Messages::TestWithSwiftTypesOptIn::CxxTypedMessage::asyncMessageReplyName): (Messages::TestWithSwiftTypesOptIn::CxxTypedMessage::CxxTypedMessage): (Messages::TestWithSwiftTypesOptIn::CxxTypedMessage::encode): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessage::name): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessage::asyncMessageReplyName): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessage::SwiftTypedMessage): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessage::encode): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessageWithoutReply::name): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessageWithoutReply::SwiftTypedMessageWithoutReply): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessageWithoutReply::encode): (Messages::TestWithSwiftTypesOptIn::SwiftTypedSynchronousMessage::name): (Messages::TestWithSwiftTypesOptIn::SwiftTypedSynchronousMessage::SwiftTypedSynchronousMessage): (Messages::TestWithSwiftTypesOptIn::SwiftTypedSynchronousMessage::encode): (Messages::TestWithSwiftTypesOptIn::CxxTypedSynchronousMessage::name): (Messages::TestWithSwiftTypesOptIn::CxxTypedSynchronousMessage::CxxTypedSynchronousMessage): (Messages::TestWithSwiftTypesOptIn::CxxTypedSynchronousMessage::encode): (Messages::TestWithSwiftTypesOptIn::CxxTypedMessageReply::name): (Messages::TestWithSwiftTypesOptIn::CxxTypedMessageReply::CxxTypedMessageReply): (Messages::TestWithSwiftTypesOptIn::CxxTypedMessageReply::encode): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessageReply::name): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessageReply::SwiftTypedMessageReply): (Messages::TestWithSwiftTypesOptIn::SwiftTypedMessageReply::encode): * Source/WebKit/Shared/IPCTester.cpp: (WebKit::nodesAreEqual): (WebKit::IPCTester::sendSwiftTypesMessagesToReceiver): (WebKit::IPCTester::addReceiverForSwiftTypesTesting): (WebKit::IPCTester::removeReceiverForSwiftTypesTesting): * Source/WebKit/Shared/IPCTester.h: * Source/WebKit/Shared/IPCTester.messages.in: * Source/WebKit/Shared/IPCTester.serialization.in: * Source/WebKit/Shared/IPCTesterPayload.h: Added. (WebKit::IPCTesterNode::create): (WebKit::IPCTesterNode::name const): (WebKit::IPCTesterNode::children const): (WebKit::IPCTesterNode::IPCTesterNode): (WebKit::ipcTesterExclaimed): (WebKit::ipcTesterTransformed): (WebKit::ipcTesterMirrored): (WebKit::ipcTesterNodeCount): (WebKit::ipcTesterDescription): * Source/WebKit/Shared/IPCTesterReceiver.cpp: (WebKit::IPCTesterReceiver::transformInner): (WebKit::IPCTesterReceiver::transformInnerSwift): (WebKit::IPCTesterReceiver::transformPayloadSwift): (WebKit::IPCTesterReceiver::transformPayloadSynchronouslySwift): (WebKit::IPCTesterReceiver::transformNodeSwift): (WebKit::IPCTesterReceiver::describeSwift): (WebKit::IPCTesterReceiver::halveEvenNumberSwift): (WebKit::IPCTesterReceiver::recordSwift): (WebKit::IPCTesterReceiver::takeRecordedSwift): (WebKit::IPCTesterReceiver::clearRecordedSwift): * Source/WebKit/Shared/IPCTesterReceiver.h: * Source/WebKit/Shared/IPCTesterReceiver.messages.in: * Source/WebKit/Shared/IPCTesterReceiver.swift: (IPCTesterReceiver.recordedTexts): (IPCTesterReceiver.transformInner(_:inner:)): (IPCTesterReceiver.transformInnerSwift(_:inner:)): (IPCTesterReceiver.transformPayloadSwift(_:payload:)): (IPCTesterReceiver.halveEvenNumberSwift(_:value:)): (IPCTesterReceiver.recordSwift(_:text:)): (IPCTesterReceiver.takeRecordedSwift(_:)): (IPCTesterReceiver.clearRecordedSwift(_:)): (IPCTesterReceiver.exclaimed(_:)): (IPCTesterReceiver.transformed(_:)): (IPCTesterReceiver.mirrored(_:)): (IPCTesterReceiver.nodeCount(_:)): * Source/WebKit/Shared/WebKit-Swift.h: * Source/WebKit/WebKit.xcodeproj/project.pbxproj: * Source/cmake/WebKitSwiftFlags.cmake: * Tools/Scripts/webkitpy/api_tests/allowlist.txt: * Tools/TestWebKitAPI/CMakeLists.txt: * Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: * Tools/TestWebKitAPI/Tests/WTF/NonEscapableBorrow.cpp: Added. (TestWebKitAPI::TEST(WTF_NonEscapableBorrow, ViewReachesTheLentObject)): (TestWebKitAPI::TEST(WTF_NonEscapableBorrow, CopiesReachTheLentObjectWhileItIsLent)): (TestWebKitAPI::TEST(WTF_NonEscapableBorrow, ObjectCanBeLentAgain)): (TestWebKitAPI::TEST(WTF_NonEscapableBorrow, NestedLenders)): (TestWebKitAPI::TEST(WTF_NonEscapableBorrowDeathTest, CopyUsedAfterTheLendEndsCrashes)): (TestWebKitAPI::TEST(WTF_NonEscapableBorrowDeathTest, CopyOfACopyReadAfterTheLendEndsCrashes)): (TestWebKitAPI::TEST(WTF_NonEscapableBorrowDeathTest, MAYBE_ASSERT_ENABLED_DEATH_TEST(ObjectDestroyedWhileLentCrashes)): Canonical link: https://commits.webkit.org/325878@main
https://bugs.webkit.org/show_bug.cgi?id=330333 rdar://191947927 Reviewed by Geoffrey Garen. Add short AGENTS files describing architectural rules, invariants and future direction for the style and CSS subsystems. The idea is to cover things that are important and that agents have a hard time figuring out from local, file-level context alone. This should improve the quality of output for everyone working on these subsystems. The initial versions are based on actual problems encountered over the last few months. AGENTS.md is read by most coding agents. Claude Code reads it only when there is no CLAUDE.md in the directory or above, and many checkouts have a personal root CLAUDE.md, so each directory also gets a CLAUDE.md that imports AGENTS.md. * .gitignore: Ignore only the root CLAUDE.md so the per-directory ones can be committed. * Source/WebCore/css/AGENTS.md: Added. * Source/WebCore/css/CLAUDE.md: Added. * Source/WebCore/style/AGENTS.md: Added. * Source/WebCore/style/CLAUDE.md: Added. Canonical link: https://commits.webkit.org/325879@main
https://bugs.webkit.org/show_bug.cgi?id=330157 Reviewed by Darin Adler. Replace the map of renderer to CacheImage that RenderView keeps for image animation pausing with a set of just the renderers. This allows accurately pausing/unpausing all the images associated with the renderer. To make this work, this introduces the ability to iterate all the Style::Images on a renderer via a new forEachStyleImage() virtual function along with additional plumbing on Style::Image and WebCore::CachedImage for animation state. Also replace the std::optional<bool> used to indicate "allow animation" with a new enum ImageAnimationOverride. Test: fast/images/pagewide-play-pause-svg-image-sources.html * LayoutTests/TestExpectations: * LayoutTests/fast/images/pagewide-play-pause-svg-image-sources-expected.txt: Added. * LayoutTests/fast/images/pagewide-play-pause-svg-image-sources.html: Added. * LayoutTests/fast/images/resources/animated-green-box.svg: Added. * LayoutTests/platform/ios/TestExpectations: * LayoutTests/platform/mac-wk2/TestExpectations: * Source/WebCore/html/HTMLImageElement.cpp: * Source/WebCore/html/HTMLImageElement.h: * Source/WebCore/loader/cache/CachedImage.cpp: * Source/WebCore/loader/cache/CachedImage.h: * Source/WebCore/loader/images/Image.h: * Source/WebCore/platform/graphics/ImageTypes.h: * Source/WebCore/rendering/HitTestResult.cpp: * Source/WebCore/rendering/HitTestResult.h: * Source/WebCore/rendering/RenderElement.cpp: * Source/WebCore/rendering/RenderElement.h: * Source/WebCore/rendering/RenderImage.cpp: * Source/WebCore/rendering/RenderImage.h: * Source/WebCore/rendering/RenderImageResource.h: * Source/WebCore/rendering/RenderListOutsideMarker.cpp: * Source/WebCore/rendering/RenderListOutsideMarker.h: * Source/WebCore/rendering/RenderView.cpp: * Source/WebCore/rendering/RenderView.h: * Source/WebCore/rendering/svg/RenderSVGImage.cpp: * Source/WebCore/rendering/svg/RenderSVGImage.h: * Source/WebCore/rendering/svg/RenderSVGResourceFEImage.cpp: * Source/WebCore/rendering/svg/RenderSVGResourceFEImage.h: * Source/WebCore/rendering/svg/legacy/LegacyRenderSVGImage.cpp: * Source/WebCore/rendering/svg/legacy/LegacyRenderSVGImage.h: * Source/WebCore/style/values/images/kinds/StyleCachedImage.cpp: * Source/WebCore/style/values/images/kinds/StyleCachedImage.h: * Source/WebCore/style/values/images/kinds/StyleImage.h: * Source/WebCore/style/values/images/kinds/StyleMultiImage.cpp: * Source/WebCore/style/values/images/kinds/StyleMultiImage.h: * Source/WebCore/testing/Internals.cpp: * Source/WebKit/WebProcess/WebPage/ios/WebPageIOS.mm: Canonical link: https://commits.webkit.org/325880@main
https://bugs.webkit.org/show_bug.cgi?id=330279 rdar://178158917 Reviewed by Tadeu Zagallo. This patch makes %TypedArray%.prototype.join faster. 1. For non shared integer TypedArray, we have extreme fast path "joinIntegerTypedArray". We only apply this to non shared array as this scans entire array to know the length of generated string first, but shared array can change elements concurrently. 2. In the other cases, we add JSTypedArrayJoiner, which incrementally ensures the buffer size. ToT Patched typed-array-join-float64 29.5397+-0.9507 ^ 7.1845+-0.1148 ^ definitely 4.1116x faster typed-array-join-int32-separator 95.8649+-2.3456 ^ 17.7610+-1.2913 ^ definitely 5.3975x faster typed-array-join-uint8 66.8946+-1.7089 ^ 6.5944+-0.8064 ^ definitely 10.1441x faster typed-array-join-float64-integers 89.3071+-2.2896 ^ 10.5858+-0.3497 ^ definitely 8.4365x faster typed-array-join-float32 28.8638+-0.4050 ^ 7.5480+-0.2421 ^ definitely 3.8240x faster typed-array-join-shared-int32-separator 95.3301+-2.9318 ^ 18.7518+-0.6931 ^ definitely 5.0838x faster typed-array-join-shared-uint8 66.8511+-0.6475 ^ 9.1109+-0.2016 ^ definitely 7.3375x faster typed-array-join-bigint64 106.2910+-2.6682 ^ 9.9683+-0.2517 ^ definitely 10.6629x faster Tests: JSTests/stress/typedarray-join-floats-and-shared.js JSTests/stress/typedarray-join-integers.js Tools/TestWebKitAPI/Tests/WTF/StringConcatenate.cpp * JSTests/microbenchmarks/typed-array-join-bigint64.js: Added. (test): * JSTests/microbenchmarks/typed-array-join-float32.js: Added. (next): (test): * JSTests/microbenchmarks/typed-array-join-float64-integers.js: Added. (test): * JSTests/microbenchmarks/typed-array-join-float64.js: Added. (next): (test): * JSTests/microbenchmarks/typed-array-join-int32-separator.js: Added. (next): (test): * JSTests/microbenchmarks/typed-array-join-shared-int32-separator.js: Added. (next): (test): * JSTests/microbenchmarks/typed-array-join-shared-uint8.js: Added. (test): * JSTests/microbenchmarks/typed-array-join-uint8.js: Added. (test): * JSTests/stress/typedarray-join-floats-and-shared.js: Added. (shouldBe): (reference): (check): (next): (fillRandomBits): (fillRandomNumbers): * JSTests/stress/typedarray-join-integers.js: Added. (shouldBe): (shouldThrowTypeError): (reference): (check): * Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h: (JSC::genericTypedArrayViewProtoFuncJoin): * Source/JavaScriptCore/runtime/JSStringJoiner.cpp: (JSC::ByteIntegerStrings::ByteIntegerStrings): (JSC::appendStringToData): (JSC::joinIntegerTypedArray): (JSC::JSTypedArrayJoiner::JSTypedArrayJoiner): (JSC::JSTypedArrayJoiner::ensureRoom): (JSC::JSTypedArrayJoiner::expandBuffer): (JSC::JSTypedArrayJoiner::separatorLength const): (JSC::JSTypedArrayJoiner::appendSeparator const): (JSC::CharacterType>::appendElements): (JSC::CharacterType>::append): (JSC::CharacterType>::appendSeparators): (JSC::CharacterType>::join): (JSC::joinTypedArray): * Source/JavaScriptCore/runtime/JSStringJoiner.h: * Source/WTF/wtf/text/IntegerToStringConversion.h: (WTF::lengthOfIntegerAsStringImpl): (WTF::lengthOfIntegerAsString): * Tools/TestWebKitAPI/Tests/WTF/StringConcatenate.cpp: (TestWebKitAPI::testLengthOfIntegerAsStringAtPowersOf10): (TestWebKitAPI::TEST(WTF, StringConcatenate_LengthOfIntegerAsString)): Canonical link: https://commits.webkit.org/325881@main
…is cut off in Safari https://bugs.webkit.org/show_bug.cgi?id=330329 <rdar://problem/190264355> Reviewed by Antti Koivisto. <div style="width: 50px; font: 10px/1 Ahem; overflow-wrap: anywhere"><span style="white-space: nowrap">XXX</span><span style="white-space: nowrap">XXX</span></div> The second span should be on the second line. Instead it stays on the first line and overflows it. https://drafts.csswg.org/css-text-3/#line-break-details "For soft wrap opportunities defined by the boundary between two characters or atomic inlines, the white-space property on the nearest common ancestor of the two characters controls breaking" The boundary between the two spans belongs to the <div>, which allows wrapping and has overflow-wrap: anywhere. However InlineContentBreaker only checks the text run's own style (nowrap) when looking for a breaking position, so it never considers breaking at this boundary. Let's check the style of the box that contains the inline box boundary after an unbreakable text run (the parent of the closing inline box, or the parent of the opening inline box when the text is not wrapped in one e.g. display: contents), both before (tryBreakingPreviousNonOverflowingRuns) and after (tryBreakingNextOverflowingRuns) the overflowing run. Tests: imported/w3c/web-platform-tests/css/css-text/overflow-wrap/overflow-wrap-anywhere-nowrap-span-001.html imported/w3c/web-platform-tests/css/css-text/overflow-wrap/overflow-wrap-break-word-nowrap-span-001.html * LayoutTests/imported/w3c/web-platform-tests/css/css-text/overflow-wrap/overflow-wrap-anywhere-nowrap-span-001-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-text/overflow-wrap/overflow-wrap-anywhere-nowrap-span-001.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-text/overflow-wrap/overflow-wrap-break-word-nowrap-span-001-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-text/overflow-wrap/overflow-wrap-break-word-nowrap-span-001.html: Added. * Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.cpp: (WebCore::Layout::wrappingStyle): Moved out of processOverflowingContent. (WebCore::Layout::InlineContentBreaker::processOverflowingContent const): (WebCore::Layout::InlineContentBreaker::overflowWrapOpportunityAfter const): (WebCore::Layout::InlineContentBreaker::tryBreakingPreviousNonOverflowingRuns const): (WebCore::Layout::InlineContentBreaker::tryBreakingNextOverflowingRuns const): * Source/WebCore/layout/formattingContexts/inline/InlineContentBreaker.h: Canonical link: https://commits.webkit.org/325882@main
…laky https://bugs.webkit.org/show_bug.cgi?id=330376 Reviewed by Patrick Griffis. The test zooms out from its load handler and finishes immediately. Zooming out shrinks the page, and TileController changes its tile size 500ms later, which paints all tiles again. Depending on whether the snapshot is taken before or after that, a few pixels differ in both SVG engines. Follow 295426@main and disable the tile size update delay, which removes the flakiness. This way tiles get their final size before the snapshot. * LayoutTests/platform/mac-tahoe-wk2-lbse-text/TestExpectations: * LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/zoom/page/zoom-svg-through-object-with-percentage-size-expected.png: Removed. * LayoutTests/svg/zoom/page/zoom-svg-through-object-with-percentage-size.xhtml: Canonical link: https://commits.webkit.org/325883@main
https://bugs.webkit.org/show_bug.cgi?id=330382 rdar://191992083 Unreviewed CI change. Call `cmake --build` instead of plain `ninja` so that we measure the impact of adaptive unified sources. * Tools/Scripts/measure-build-time: Canonical link: https://commits.webkit.org/325884@main
https://bugs.webkit.org/show_bug.cgi?id=330161 rdar://191837232 Reviewed by Tim Nguyen. Upstream commit: web-platform-tests/wpt@e78a5ca * LayoutTests/TestExpectations: * LayoutTests/imported/w3c/resources/resource-files.json: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/WEB_FEATURES.yml: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/animated-clip-path.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/animated-gif-pinned-to-element-image.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/animated-gif.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/canvas-content-drawable-stacking-context.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/canvas-in-custom-element-multiple.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/canvas-in-custom-element.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/changes-in-paint-event.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/changing-size-in-paint-event.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-contain-tall-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-contain-tall.tentative-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-contain-tall.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-contain-wide-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-contain-wide.tentative-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-contain-wide.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-cover-tall-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-cover-tall.tentative-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-cover-tall.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-cover-wide-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-cover-wide.tentative-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-cover-wide.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-fill-tall-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-fill-tall.tentative-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-fill-tall.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-fill-wide-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-fill-wide.tentative-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-fill-wide.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-none-tall-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-none-tall.tentative-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-none-tall.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-none-wide-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-none-wide.tentative-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/css-object-fit-none-wide.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/fullscreen-child-crash.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/fullscreen-crash.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-contain-tall.tentative-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-contain-tall.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-contain-wide.tentative-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-contain-wide.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-cover-tall.tentative-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-cover-tall.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-cover-wide.tentative-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-cover-wide.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-fill-tall.tentative-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-fill-tall.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-fill-wide.tentative-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-fill-wide.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-none-tall.tentative-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-none-tall.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-none-wide.tentative-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/elementsFromPoint-object-fit-none-wide.tentative.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/low-dpi-hit-test.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/hit-test/w3c-import.log: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/iframe.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/ink-overflow.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/invalidation-during-onpaint.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/moved-webgl-canvas.tentative-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/moved-webgl-canvas.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/onpaint-invalidation-crash.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/onpaint-outside-invalidation-crash.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/onpaint-scroll-crash.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/filtered-div-removed-contain-paint.tentative.https.sub-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/filtered-div-removed-contain-paint.tentative.https.sub.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/svg/svg-pattern-filter-transformed-text.tentative.https.sub-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/svg/svg-pattern-filter-transformed-text.tentative.https.sub.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/svg/svg-pattern-with-feImage-transformed-text.tentative.https.sub-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/svg/svg-pattern-with-feImage-transformed-text.tentative.https.sub.html: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/svg/w3c-import.log: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/target-text-ignored-overlay-path-ref.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/target-text-ignored-overlay-path.tentative-expected.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/privacy/w3c-import.log: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/resources/CanvasWidget.js: (CanvasWidget.prototype.connectedCallback): (CanvasWidget): * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/scale.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/scroller-crash.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/video.tentative.html: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/element/manual/draw-element-image/w3c-import.log: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/draw-element-image/WEB_FEATURES.yml: Added. * LayoutTests/imported/w3c/web-platform-tests/html/canvas/offscreen/manual/draw-element-image/w3c-import.log: * LayoutTests/imported/w3c/web-platform-tests/html/canvas/resources/wait-for-canvas-paint.js: (waitForCanvasPaint): Canonical link: https://commits.webkit.org/325885@main
https://bugs.webkit.org/show_bug.cgi?id=330377 Unreviewed gardening. Update the TestExpectations for both mac-tahoe-wk2-lbse-text (LBSE-only) and mac-tahoe-wk2-pixel (legacy SVG engine) that we use for testing LBSE correctness. Lots of flaky markers can be removed. Both LBSE/legacy pixel test runs now pass 100%. This is a preparation to move to macOS Golden Gate. * LayoutTests/platform/mac-tahoe-wk2-lbse-text/TestExpectations: * LayoutTests/platform/mac-tahoe-wk2-lbse-text/imported/w3c/web-platform-tests/svg/text/reftests/tiny-text-with-scaling-expected.png: Added. * LayoutTests/platform/mac-tahoe-wk2-lbse-text/imported/w3c/web-platform-tests/svg/text/reftests/tiny-text-with-scaling-expected.txt: Added. * LayoutTests/platform/mac-tahoe-wk2-lbse-text/svg/W3C-SVG-1.1/fonts-desc-02-t-expected.png: Removed. * LayoutTests/platform/mac-tahoe-wk2-pixel/TestExpectations: * LayoutTests/platform/mac-tahoe-wk2-pixel/imported/w3c/web-platform-tests/svg/text/reftests/tiny-text-with-scaling-expected.png: Added. Canonical link: https://commits.webkit.org/325886@main
…tarted https://bugs.webkit.org/show_bug.cgi?id=324707 Reviewed by Alexey Proskuryakov. WebAutomationSession registers one pending callback per page when a command starts a navigation, and any main-frame completion on that page resolved it. A browsing context created by automation still has its initial about:blank load in flight, so a navigate sent right after returned when that load finished, before the requested one committed; a following browsingContext.getTree then reported about:blank with no children. A script-driven same-document navigation in the old document completed the command the same way. Keep the API::Navigation that navigate, reload, go back, go forward and traverseHistory start, and complete the wait for that navigation, or for one the UI process learned of later, which replaced it. Navigation identifiers cannot tell the two apart since web processes mint the identifiers of the navigations they start, so API::Navigation gets a sequence number in the order the UI process created the objects. Same-document targets (a fragment of the committed document's URL, or a history entry of the same document) keep the previous behavior, because WebCore reports them with the existing document's navigation; for the same reason a same-document navigation completes only the waits that are not bound to a navigation. A navigation that failed never reaches the document load an eager wait ends with, so its failure completes the eager waits it matches as well; the other eager waits that are not bound to a navigation (waitForNavigationToComplete) still end with the document load only. A navigation that is destroyed without having reported its end, because another load cancelled its policy check, can be replaced by a load that has no navigation, such as the error page the GLib ports show for a failed load; the waits bound to it then end with the end of any load that is not an earlier one, as they did before, but not with a same-document navigation of the old document. The load timer is stopped only when no wait remains. Also emit browsingContext.load, navigationFailed and fragmentNavigated before completing the pending command. load used to be emitted after the command was resolved, so a navigate with wait=complete returned ahead of the event it had waited for; in session/unsubscribe/subscriptions.py this made test_unsubscribe_partially_from_one_event abort and leak its subscription into the next test. Tests: imported/w3c/webdriver/tests/bidi/browsing_context/navigate/ imported/w3c/webdriver/tests/bidi/browsing_context/reload/ imported/w3c/webdriver/tests/bidi/session/unsubscribe/subscriptions.py Tools/TestWebKitAPI/Tests/WebKit/WKWebView/glib/TestAutomationSession.cpp * Source/WebKit/UIProcess/API/APINavigation.cpp: (API::Navigation::generateSequenceNumber): Added. * Source/WebKit/UIProcess/API/APINavigation.h: A sequence number in the order the UI process learned of the navigations. * Source/WebKit/UIProcess/Automation/WebAutomationSession.cpp: (WebKit::addPendingNavigationCallback): Accept either kind of pending callback. (WebKit::WebAutomationSession::waitForNavigationToCompleteOnPage): Keep the awaited navigation, or that the target is in the same document. (WebKit::WebAutomationSession::respondToPendingPageNavigationCallbacksWithTimeout): (WebKit::WebAutomationSession::navigateBrowsingContext): Await the started navigation unless the target is a fragment of the committed document. (WebKit::WebAutomationSession::waitForHistoryTraversalToComplete): A traversal between entries of the same document is awaited as a same-document navigation; the navigation's own from and target items decide. (WebKit::WebAutomationSession::goBackInBrowsingContext): (WebKit::WebAutomationSession::goForwardInBrowsingContext): (WebKit::WebAutomationSession::traverseHistoryInBrowsingContext): (WebKit::WebAutomationSession::reloadBrowsingContext): (WebKit::WebAutomationSession::respondToPendingNavigationCallbacksWithSuccess): Keep the timer while waits remain. (WebKit::WebAutomationSession::hasPendingNavigationCallbacks): Added. (WebKit::WebAutomationSession::takePendingPageNavigationCallbacks): The finished navigation, passed by the caller, completes a wait for itself or for a navigation with a lower sequence number, and any load completes a wait whose navigation was destroyed. Waits without a navigation complete when the caller says so, or for a same-document target. (WebKit::WebAutomationSession::navigationOccurredForFrame): Take the finished navigation and the kind of notification; complete the eager waits bound to it or to a same-document target too. (WebKit::WebAutomationSession::navigationDestroyed): Added. (WebKit::WebAutomationSession::documentLoadedForFrame): (WebKit::WebAutomationSession::willClosePage): * Source/WebKit/UIProcess/Automation/WebAutomationSession.h: * Source/WebKit/UIProcess/WebPageProxy.cpp: (WebKit::WebPageProxy::didDestroyNavigationShared): Tell the session before the navigation is gone. (WebKit::WebPageProxy::didFailProvisionalLoadForFrameShared): Pass the failed navigation, after emitting navigationFailed. (WebKit::WebPageProxy::didFinishLoadForFrame): Pass the navigation, after emitting load. (WebKit::WebPageProxy::didFailLoadForFrame): Ditto, after emitting navigationFailed. (WebKit::WebPageProxy::didSameDocumentNavigationForFrame): Complete after emitting fragmentNavigated, as a same-document navigation without a navigation. (WebKit::WebPageProxy::didSameDocumentNavigationForFrameViaJS): Ditto. * Tools/TestWebKitAPI/Tests/WebKit/WKWebView/glib/TestAutomationSession.cpp: (holdPolicyDecisionForHeldRequest): Added. (checkNavigationCommandsAwaitTheirOwnNavigation): Added. A navigate while an earlier load is provisional, a pushState and a fragment change of the loading document, a page-started navigation that cancels the awaited one's policy check, with and without a pushState of the old document while the replacement loads, a navigate while an error page loads, an eager wait whose navigation is cancelled, and an eager waitForNavigationToComplete while the old page's load is stopped. (serverCallback): Added. (beforeAll): (afterAll): * WebDriverTests/TestExpectations.json: Updated from a GTK run; the entries are for all ports. Canonical link: https://commits.webkit.org/325887@main
…d no fallback content https://bugs.webkit.org/show_bug.cgi?id=325037 rdar://188225123 Reviewed by Anne van Kesteren. FocusController::previousFocusableElementOrScopeOwner() asserted that every focus navigation scope has a last node, but the fallback scope of a slot with no assigned nodes and no children is empty. Return nullptr for an empty scope, as Release builds already did and nextFocusableElementOrScopeOwner() does. 321227@main gave every optgroup in a select a user agent shadow tree with a slot, so an empty optgroup now creates such a scope. On iOS, WebPage::focusedElementInformationWithoutLayout() searches backward to set hasPreviousNode, which is how imported/w3c/web-platform-tests/editing/crashtests/inserthtml-in-li-in-option.html hit the assertion. Test: fast/shadow-dom/focus-navigation-backward-across-empty-slot.html Canonical link: https://commits.webkit.org/325888@main
…ideo playback https://bugs.webkit.org/show_bug.cgi?id=329525 rdar://162447105 Reviewed by Andy Estes. The player's fullscreen is a fixed overlay sized to the viewport rather than element or native fullscreen, so the page remains an ordinary scrolling page and its canvas background is visible wherever content does not cover. The page leaves <html> and <body> transparent, painting its dark design on inner elements, and declares no color-scheme. Document::useDarkAppearance() therefore returns false and the canvas resolves to the light system background, which shows at the screen edges while rotating and in the region outside the layout viewport at rest. Add NeedsDarkAppearanceWithoutColorSchemeQuirk, which makes useDarkAppearance() return true for this page so the canvas resolves to the dark system background. Test: fast/quirks/dark-appearance-without-color-scheme-quirk.html * LayoutTests/fast/quirks/active-quirks-by-domain-expected.txt: * LayoutTests/fast/quirks/dark-appearance-without-color-scheme-quirk-expected.txt: Added. * LayoutTests/fast/quirks/dark-appearance-without-color-scheme-quirk.html: Added. * LayoutTests/platform/glib/fast/quirks/active-quirks-by-domain-expected.txt: * LayoutTests/platform/ios/fast/quirks/active-quirks-by-domain-expected.txt: * LayoutTests/platform/ipad/fast/quirks/active-quirks-by-domain-expected.txt: * LayoutTests/platform/mac-sequoia/fast/quirks/active-quirks-by-domain-expected.txt: * LayoutTests/platform/mac-tahoe/fast/quirks/active-quirks-by-domain-expected.txt: * Source/WebCore/dom/Document.cpp: (WebCore::Document::useDarkAppearance const): * Source/WebCore/page/QuirkBehaviors.yaml: * Source/WebCore/page/QuirkTable.json: Canonical link: https://commits.webkit.org/325889@main
…s with the site-isolation flavor https://bugs.webkit.org/show_bug.cgi?id=330283 rdar://191888854 Reviewed by Alexey Proskuryakov. --site-isolation now sets the site-isolation result flavor, as it does in run-webkit-tests and run-api-tests, so runs with and without Site Isolation upload to different configurations. The upload test's example suite was named for Site Isolation, so rename it. * Tools/Scripts/run-webdriver-tests: * Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_unittest.py: (WebDriverTestRunnerUploadTest.test_upload_with_suite): Canonical link: https://commits.webkit.org/325890@main
https://bugs.webkit.org/show_bug.cgi?id=330282 rdar://191887931 Reviewed by Alexey Proskuryakov. Add Apple-Tahoe-Debug-WebDriver-Site-Isolation-Tests, which passes --site-isolation to run-webdriver-tests. Apple-Tahoe-Debug-Build triggers it as it does Apple-Tahoe-Debug-WebDriver-Tests, and the two testers share bot10015. * Tools/CISupport/build-webkit-org/config-template.yaml: * Tools/CISupport/build-webkit-org/factories_unittest.py: (TestExpectedBuildSteps): Canonical link: https://commits.webkit.org/325891@main
…report success on the UIProcess target without doing anything https://bugs.webkit.org/show_bug.cgi?id=330181 rdar://191846518 Reviewed by Zak Ridouh and Basuke Suzuki. Page.getCookies, setCookie and deleteCookie are declared for the page target only, so the frontend sends them to the main-frame process's InspectorPageAgent, and under Site Isolation it reads cookies through the Storage domain instead. ProxyingPageAgent still has to implement them because the generated PageBackendDispatcherHandler declares every Page command, and the backend dispatcher does not check target types, so a raw protocol message to the UIProcess target still reaches these handlers. setCookie and deleteCookie returned success without doing anything, and the FIXME above them pointed at a resolved bug as if forwarding work remained. Make all three return an error that names the Storage command to use, and replace the FIXME with a comment explaining why the handlers exist. There are no new tests, because the frontend cannot send these commands to the UIProcess target. * Source/WebKit/UIProcess/Inspector/Agents/ProxyingPageAgent.cpp: (Inspector::ProxyingPageAgent::getCookies): (Inspector::ProxyingPageAgent::setCookie): (Inspector::ProxyingPageAgent::deleteCookie): Canonical link: https://commits.webkit.org/325892@main
… load events instead of deferring them https://bugs.webkit.org/show_bug.cgi?id=329027 rdar://191068101 Reviewed by Zak Ridouh. A document held by the debugger (a frame stopped in it, or a frame of the same page held by a debugger pause session) is suspended with JavaScriptDebuggerPaused and its ScriptController is paused. That defers everything that goes through the event loop, but lifecycle events are dispatched synchronously and JSEventListener skips every listener while the script is paused. A document that finishes loading while held, or the stopped document itself, therefore loses readystatechange, DOMContentLoaded, load, pageshow and the load and error events of its images, links, styles and iframes for good. Defer these events at dispatch granularity (per listener does not work: the event state is reset after the dispatch and a once listener is already removed). EventDispatcher::dispatchEvent(Node&, Event&) and LocalDOMWindow::dispatchEvent(Event&, EventTarget*) ask Document::shouldDeferLifecycleEventForDebugger(), which holds for a trusted pageshow, or a non-cancelable load, error, DOMContentLoaded or readystatechange, while the document is suspended with JavaScriptDebuggerPaused and its frame's script is paused. The event is replayed in a DOMManipulation task, which waits for the release because the hold suspends the document's task group. A per-document count of queued events keeps a later lifecycle event from overtaking them. Only the dispatch is deferred, not the load. Replayed handlers see the state the document reached while held (readyState is already complete, the timing marks and Inspector load markers are already recorded), a queued element event can no longer be canceled, and events outside this set can run before the queued ones. All of these events were dropped for good before. Holding the load itself is not an option: WebLoaderStrategy::setDefersLoading() is empty. The deferral applies with or without Site Isolation, because PageDebugger holds documents the same way. pagehide is left out: a deferred one would be dispatched after a back/forward cache restore. * LayoutTests/http/tests/inspector/debugger/pause-defers-lifecycle-events-of-frame-loading-during-pause-expected.txt: Added. * LayoutTests/http/tests/inspector/debugger/pause-defers-lifecycle-events-of-frame-loading-during-pause.html: Added. A same-origin iframe finishes loading while the main frame is stopped and gets its events after Resume. A second case removes the frame while its events are deferred. * LayoutTests/http/tests/inspector/debugger/pause-defers-load-events-of-stopped-document-expected.txt: Added. * LayoutTests/http/tests/inspector/debugger/pause-defers-load-events-of-stopped-document.html: Added. Images that finish loading while their own document is stopped get their load and error events after Resume. * LayoutTests/http/tests/inspector/debugger/resources/lifecycle-events-frame.html: Added. * LayoutTests/http/tests/site-isolation/inspector/debugger/pause-holds-loading-frame-defers-lifecycle-events-expected.txt: Added. * LayoutTests/http/tests/site-isolation/inspector/debugger/pause-holds-loading-frame-defers-lifecycle-events.html: Added. The same for a cross-site iframe held by the session. The events must match a load without a pause (order, target, trusted flag, once listener), and an untrusted load dispatched by script while held stays synchronous. * Source/WebCore/dom/Document.cpp: (WebCore::Document::isDeferrableLifecycleEventForDebugger const): (WebCore::Document::queueTaskToDispatchDeferredLifecycleEvent): * Source/WebCore/dom/Document.h: * Source/WebCore/dom/DocumentInlines.h: (WebCore::Document::shouldDeferLifecycleEventForDebugger const): * Source/WebCore/dom/EventDispatcher.cpp: (WebCore::EventDispatcher::dispatchEvent): (WebCore::dispatchEventWithoutDebuggerDeferral): * Source/WebCore/page/LocalDOMWindow.cpp: (WebCore::LocalDOMWindow::dispatchEvent): (WebCore::LocalDOMWindow::dispatchEventWithoutDebuggerDeferral): * Source/WebCore/page/LocalDOMWindow.h: Canonical link: https://commits.webkit.org/325893@main
https://bugs.webkit.org/show_bug.cgi?id=329257 Reviewed by Abrar Rahman Protyasha. Adds a CPU implementation of the mesh-gradient() renderer, written to be as clear as possible for the initial version. A shader based implementation will follow. For a high level overview of the rendering process, we can think of it happening in two phases, preprocessing and drawing. Preprocessing is agnostic to the size of the output image, but drawing takes is not (e.g. the number of subdivisions / triangles to make depends on how big the output image will be). Preprocessing: 1. Convert the colors. Each point’s color is converted to the interpolation color space. 2. Perform fixup on the hues. In a cylindrical color space, each hue is moved by whole turns so that going from one point to the next takes the arc the method asks for. This goes down the first column and then along each row. 3. Build the position patches. Each cell of the grid becomes a patch. Its four edges are cubic Bézier curves from the points’ control points, and a Coons patch fills in the interior control points as described in the PDF spec. 4. Build the color patches. Each position patch gets a matching color patch. Its edges are monotone cubic curves through the colors along that row or column, so they don’t overshoot, and a Coons patch fills in the interior here too. Past the edge of the grid the colors are mirrored. Drawing: 1. Split the patches into triangles. Each patch is divided into an even grid of (u, v) cells. Patches in the same row or column use the same divisions along their shared edges, so neighboring patches meet exactly. The position and color are evaluated at each grid corner, the color is converted to premultiplied sRGB, and each cell becomes two triangles. 2. Fill the pixel buffer with the background color. 3. Fill the triangles. For each triangle the renderer visits the pixels within its bounds. If a pixel’s center is inside, its color is blended from the three corner colors using barycentric weights and written to the pixel buffer. Tests: fast/css/mesh-gradient/mesh-gradient-background.html fast/css/mesh-gradient/mesh-gradient-cache-reuse.html fast/css/mesh-gradient/mesh-gradient-horizontal.html fast/css/mesh-gradient/mesh-gradient-resize.html fast/css/mesh-gradient/mesh-gradient-solid.html Tools/TestWebKitAPI/Tests/WebCore/MeshGradientRendererTests.cpp * LayoutTests/fast/css/mesh-gradient/mesh-gradient-background-expected.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-background.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-cache-reuse-expected.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-cache-reuse.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-horizontal-expected.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-horizontal.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-resize-expected.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-resize.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-solid-expected.html: Added. * LayoutTests/fast/css/mesh-gradient/mesh-gradient-solid.html: Added. * Source/WebCore/platform/graphics/MeshGradient.cpp: * Source/WebCore/platform/graphics/MeshGradient.h: * Source/WebCore/platform/graphics/MeshGradientRenderer.h: * Source/WebCore/platform/graphics/MeshGradientRendererCPU.cpp: * Source/WebCore/platform/graphics/MeshGradientRendererCPU.h: * Tools/TestWebKitAPI/CMakeLists.txt: * Tools/TestWebKitAPI/TestWebKitAPI.xcodeproj/project.pbxproj: * Tools/TestWebKitAPI/Tests/WebCore/MeshGradientRendererTests.cpp: Added. Canonical link: https://commits.webkit.org/325894@main
https://bugs.webkit.org/show_bug.cgi?id=330350 Reviewed by Rupin Mittal. Annotate this function as NODELETE as done in internals. No new tests since there should be no behavioral changes. * Source/WebKit/Shared/WebPreferencesDefaultValues.h: Canonical link: https://commits.webkit.org/325895@main
…ns.html asserts in WebPageProxy::continueNavigationInNewProcess https://bugs.webkit.org/show_bug.cgi?id=330206 rdar://191850894 Reviewed by Sihui Liu. When the navigation's website policies specify a different data store, the new process uses that data store while the page keeps its current one until the provisional page commits. The assertion compared the new process's data store against the page's, so it failed in this case. Compare against the data store from the website policies when there is one. * Source/WebKit/UIProcess/WebPageProxy.cpp: (WebKit::WebPageProxy::continueNavigationInNewProcess): Canonical link: https://commits.webkit.org/325896@main
https://bugs.webkit.org/show_bug.cgi?id=330407 rdar://192009420 Unreviewed test gardening. * LayoutTests/platform/mac-wk2/TestExpectations: Canonical link: https://commits.webkit.org/325897@main
https://bugs.webkit.org/show_bug.cgi?id=330257 Reviewed by BJ Burg. Updated to WPT commit 711c4c6a69, from November 4th, 2026. The last update was 303718@main, at 3d8fdcd7ec from November 19th, 2025. Since then, there were 213 commits in wpt/webdriver. Some relevant changes: - New tests for WebDriver classic commands in same-origin and cross-origin frames, and for Get Window Handles with frames and popups. - New tests for features that WebKit doesn't implement yet. They're skipped, each with a bug: emulation.setMediaFeaturesOverride, setTouchOverride, setScreenSettingsOverride, setScrollbarTypeOverride, setViewportMetaOverride and setTextLayoutModeOverride, browser.setClientWindowState, browsingContext.startScreencast and stopScreencast, userAgentClientHints.setClientHintsOverride, the speculation.prefetchStatusUpdated event, and the WebAuthn, permissions and Global Privacy Control extension commands. - Tests for classic extension commands moved to classic/external/, including permissions/set.py. - The test support code was split into bidi/ and classic/ subdirectories. - wptrunner renamed WdspecExecutor to PytestExecutor. Only the Mac expectations were updated, from Debug runs with and without Site Isolation. GTK and WPE will need gardening. * Tools/Scripts/webkitpy/webdriver_tests/webdriver_test_runner_w3c.py: (WebDriverTestRunnerW3C._is_test): Like WPT, don't treat files in a support directory as tests at any depth. The new support/http_handlers/serve_video.py was run as a test, and failed to import. * Tools/Scripts/webkitpy/webdriver_tests/webdriver_w3c_executor.py: Use PytestExecutor. * WebDriverTests/TestExpectations.json: Skip the tests for features that aren't implemented, add Mac expectations for the other new failures, and remove the entry for classic/permissions/set.py, which moved. * WebDriverTests/imported/w3c/: Update imported code, and re-apply the local changes: in wptrunner's browsers/base.py and environment.py, and the DigitalCredentials module in the webdriver client. The importer doesn't remove files that upstream deleted, so these were removed by hand. All of them were moved, renamed or replaced upstream: - tools/wptrunner/wptrunner/browsers/servodriver.py and executors/executorservodriver.py were renamed to servo.py and executorservo.py. - webdriver/tests/bidi/session/new/bidi_upgrade.py moved to webdriver/tests/interop/. - webdriver/tests/classic/permissions/ moved to webdriver/tests/classic/external/permissions/. - webdriver/tests/support/fixtures_bidi.py and fixtures_http.py became support/bidi/fixtures.py and support/classic/fixtures.py. - webdriver/tests/support/html/test_actions_scroll.html was replaced by the pages in support/html/wheel/. Canonical link: https://commits.webkit.org/325898@main
rdar://191796300 https://bugs.webkit.org/show_bug.cgi?id=330095 Reviewed by Anne van Kesteren. Upstream commit: web-platform-tests/wpt@fec74d5 * LayoutTests/TestExpectations: * LayoutTests/imported/w3c/resources/resource-files.json: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/accent-color-keyword-animation-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/accent-color-keyword-animation.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/accent-color-keyword-cyclic-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/accent-color-keyword-cyclic.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/accent-color-keyword-resolution-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/accent-color-keyword-resolution.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/accent-color-text-keyword-resolution-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/accent-color-text-keyword-resolution.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/appearance-display-001-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/appearance-display-001.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/caret-color-block-shape-text-color-004-expected.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/caret-color-block-shape-text-color-004-ref.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/caret-color-block-shape-text-color-004.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-auto-sensitive-text-input-expected.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-auto-sensitive-text-input-ref.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-auto-sensitive-text-input.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-computed-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-computed.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-non-sensitive-elements-expected.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-non-sensitive-elements-ref.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-non-sensitive-elements.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-none-sensitive-text-input-expected.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-none-sensitive-text-input-ref.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-none-sensitive-text-input.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-parsing-expected.txt: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/input-security-parsing.html: Removed. * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/caret-color-computed-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/caret-color-computed.html: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/caret-color-invalid-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/caret-color-invalid.html: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/caret-color-valid-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/caret-color-valid.html: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/outline-color-computed-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/outline-color-computed.html: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/outline-valid-expected.txt: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/parsing/outline-valid.html: * LayoutTests/imported/w3c/web-platform-tests/css/css-ui/w3c-import.log: Canonical link: https://commits.webkit.org/325899@main
…enderers() https://bugs.webkit.org/show_bug.cgi?id=329763 rdar://191543407 Reviewed by Matt Woodrow. This patch aligns WebKit with Gecko / Firefox. ViewTransition::updatePseudoElementRenderers() returns an InvalidStateError when a captured new element has no renderer or its renderer is skipped content. Both callers (activateViewTransition() and handleTransitionFrame()) discarded the result, so the transition kept running with a stale ::view-transition-new() instead of being skipped as "update pseudo-element styles" requires. The no-renderer case was already caught by updatePseudoElementStylesRead(), which runs first in handleTransitionFrame(). The skipped-content case, e.g. content-visibility: hidden on an ancestor, only reaches this check, so it was silently ignored. Skip the view transition with the returned exception at both call sites, matching the neighboring checkForViewportSizeChange() / captureNewState() checks. Test: imported/w3c/web-platform-tests/css/css-view-transitions/new-element-hidden-during-animation-skips-transition.html * LayoutTests/imported/w3c/web-platform-tests/css/css-view-transitions/new-element-hidden-during-animation-skips-transition-expected.txt: Added. * LayoutTests/imported/w3c/web-platform-tests/css/css-view-transitions/new-element-hidden-during-animation-skips-transition.html: Added. * Source/WebCore/dom/ViewTransition.cpp: (WebCore::ViewTransition::activateViewTransition): (WebCore::ViewTransition::handleTransitionFrame): Canonical link: https://commits.webkit.org/325900@main
…cestor has overflow:hidden and border-radius https://bugs.webkit.org/show_bug.cgi?id=328836 rdar://191519236 Reviewed by Matt Woodrow. This patch aligns WebKit with Gecko / Firefox and Blink / Chromium. When a filtered layer's clip rect is affected by an ancestor's border-radius, RenderLayer::applyFilters() and the destination-clip callback in RenderLayer::setupFilters() clipped the filter output with applyAncestorClippingForBorderRadius() using IncludeSelfForBorderRadius. For a layer that itself has overflow:hidden and border-radius, this added a clip to its own inner (padding-box) border shape, which removed the layer's own border from the filtered result. The filter output includes the layer's own border box, so it should only be clipped by its ancestors. Pass DoNotIncludeSelfForBorderRadius in both places, matching the background and mask painting paths. Tests: imported/w3c/web-platform-tests/css/filter-effects/filter-ancestor-border-radius-overflow-hidden-border.html * LayoutTests/imported/w3c/web-platform-tests/css/filter-effects/filter-ancestor-border-radius-overflow-hidden-border-expected.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/filter-effects/filter-ancestor-border-radius-overflow-hidden-border-ref.html: Added. * LayoutTests/imported/w3c/web-platform-tests/css/filter-effects/filter-ancestor-border-radius-overflow-hidden-border.html: Added. * Source/WebCore/rendering/RenderLayer.cpp: (WebCore::RenderLayer::setupFilters): (WebCore::RenderLayer::applyFilters): Canonical link: https://commits.webkit.org/325901@main
https://bugs.webkit.org/show_bug.cgi?id=329581 Reviewed by Darin Adler. start() with a null buffer kept the source silent until the context finished, so ended fired at the end of the render, or later if a buffer was assigned in time to play. The node was treated as silent, so process() never ran and it never finished. End it on the first quantum. A buffer assigned after that does not play. audiobuffersource-start-null-buffer.html can run again. * LayoutTests/TestExpectations: * LayoutTests/imported/w3c/web-platform-tests/webaudio/the-audio-api/the-audiobuffersourcenode-interface/audiobuffersource-start-null-buffer-expected.txt: * LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-grain-no-duration-expected.txt: * LayoutTests/webaudio/AudioBufferSource/audiobuffersource-loop-grain-no-duration.html: * Source/WebCore/Modules/webaudio/AudioBufferSourceNode.cpp: (WebCore::AudioBufferSourceNode::process): (WebCore::AudioBufferSourceNode::propagatesSilence): Canonical link: https://commits.webkit.org/325902@main
https://bugs.webkit.org/show_bug.cgi?id=330275 Reviewed by Ryan Haddad. A failure in stress mode turns the build red, but only failures in the regular layout test run add the merging-blocked label to the pull request, so a pull request whose new or modified tests fail in stress mode stays unblocked when the regular run passes. Add BlockPullRequest after a failure in stress mode. The step in site isolation mode, which shares this code, keeps its current behavior. * Tools/CISupport/ews-build/steps.py: (RunWebKitTestsInStressMode.evaluateCommand): * Tools/CISupport/ews-build/steps_unittest.py: (TestRunWebKitTestsInStressMode.test_failure_blocks_pull_request): (TestRunWebKitTestsInStressMode.test_success_does_not_block_pull_request): (TestRunWebKitTestsInSiteIsolationMode.test_failure_does_not_block_pull_request): Canonical link: https://commits.webkit.org/325903@main
…is likely Upstream's table of prepared structures (WebKit/WebKit@aeca1a989f) records the keys and the slots of every object that appendUnpreparedObject() writes. The next object of that Structure is then written from the record. The record costs about 37 instructions for each property and 100 for each Structure, and it saves about 90 for each property of every later object. Most values that a server writes have one object of each Structure. With the x64 lto-aot jsc, against the engine before the merge: one object with five numbers +37% instructions one object with a nested object +31% a list of 2,000 objects of one shape -39% So a Structure is prepared where another object of it is likely: - for an element of a list of two or more, at once, as upstream does - for any other object when appendUnpreparedObject() meets its Structure the second time. What it met last is kept for each slot of the table. With a release build without LTO, against the merge as it was: one object with five numbers -17% instructions one object with ten numbers -20% one object with a nested object -13% a list of one object -15% a list of two or of three objects +1% a list of 2,000 objects, one shape 0% a list of 2,000 objects, 40 shapes 0% a list of 2,000 strings +1% Test: JSTests/stress/json-stringify-when-a-structure-is-prepared.js
670c186 to
907132b
Compare
…room for a long string Upstream starts the dynamic buffer with the length of the shorter of the last two results and 256 characters of slack (WebKit/WebKit@aeca1a989f). The fork's appendContentOfLongString() asks for six times a piece of a string before it writes the piece, up to 24,577 characters. A result with a string of 64 characters or more near its end did not fit: - hasRemainingCapacitySlow() grew the buffer to twice the length and copied the result there - result() saw a buffer of more than twice the length and copied the result again into one that fits For a list of 2,000 strings that is 210,421 characters long, that is two copies of 421 KB in every call. The x64 lto-aot jsc took 26% more cycles than the engine before the merge for the same instructions. The slack is now what hasRemainingCapacitySlow() gives a result like the last, an eighth of the length and six pieces, and no more than the length, so that result() keeps the buffer. With a release build without LTO, for that list: 25% fewer cycles and 4% fewer instructions. The test of the commit before has the text and the cases that its message describes, and results that end in a long string.
907132b to
8a6bc88
Compare
main is two commits ahead of the commit that Bun pins: #1001 and #1008. Four files conflict, each in one place: - runtime/AbstractModuleRecord.h: #1001 put an #endif in front of the declaration of tryGetCachedResolution(), whose NODELETE moved. - aot/object/AOTObjectMethodTable.cpp: defineExtraProperty() hands a value to the setter of a custom value first, then asks admitsMutation() as #1008 has it. - heap/MarkedBlockCage.cpp: #1008 prints every literal of logExhaustion() by its characters. That takes the place of the one line that this branch changed for the same reason. - aot/tests/AOTCollectorTests.cpp: #1008 gives the processes of the collector tests pauses of 10 s, so that a collection marks with the mutator stopped. The test of this branch for a collector thread that marks beside a running mutator keeps the pauses of a program: with the long ones no collection reaches its concurrent phase. Without the change that the test is for (3b77c53), a release build passes it in 40 of 40 runs with the long pauses. With the pauses of a program its process does not end in 7 of 40 runs. One change is in neither parent: - aot/facts/AOTLinkCalls.cpp: whatTableSaysOf(), new in #1008, calls WTF::atomicLoad() and WTF::atomicStore() with a std::memory_order. Since WebKit/WebKit@6ab0aebc81bc the order is a template argument. Built here: jsc and testaot, Release with assertions, Linux x64, no LTO. `testaot all`: 5205 passed, 0 failed, 17 todo, 25 left out.
8a6bc88 to
2f97fc8
Compare
There was a problem hiding this comment.
Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.
Additional findings (outside the current diff — GitHub can't attach inline comments there):
-
🟡
Source/JavaScriptCore/runtime/JSObject.cpp:4690— Scripts calling Object.defineProperty on a custom-value property whose native setter refuses the value now get a silent no-op instead of a TypeError or a stored value. The Bun block at JSObject.cpp:4690 returns the setter's bool straight out of validateAndApplyPropertyDescriptor, ignoring throwException, so a false return with no pending exception reaches callers that only propagate exceptions. Fix: when the setter returns false without throwing and throwException is true, throw a TypeError (as the function's other rejections do via typeError), while Reflect.defineProperty keeps returning false as the new test expects.Why this was flagged
A CustomValue property whose PutValueFunc returns false for some inputs without throwing, such as customSetValue in Source/JavaScriptCore/tools/JSDollarVM.cpp:1854 which returns false for a non-object, reached through Object.defineProperty(o, name, { value }) or a class field on a returned object. The new block at Source/JavaScriptCore/runtime/JSObject.cpp:4685-4691 does RELEASE_AND_RETURN(scope, setter(...)) and never looks at throwException. objectConstructorDefineProperty at Source/JavaScriptCore/runtime/ObjectConstructor.cpp:944 passes true and discards the bool, relying on the callee to throw. So the script sees defineProperty return the object with the property unchanged and no error; on the base branch the same call replaced the custom value with the given value and succeeded. The new test only checks Reflect.defineProperty, which is specified to return false, so the Object.defineProperty case has no coverage. The spec requires Object.defineProperty to throw a TypeError when [[DefineOwnProperty]] returns false.
Verification: Source/JavaScriptCore/runtime/JSObject.cpp:4690 returns the setter's bool verbatim;
throwExceptionis never consulted. The callerobjectConstructorDefinePropertyat Source/JavaScriptCore/runtime/ObjectConstructor.cpp:944 ignores the return value and returnsobjat 945 unless an exception is pending. So a false return with no exception yields no TypeError, where the base branch stored the value viaputDirect. -
🟡
Source/JavaScriptCore/runtime/Options.cpp:654— Bun users on Linux arm64 hosts or containers with 4 or fewer CPUs get FTL tier-up 4x later than on the base branch. Source/JavaScriptCore/runtime/Options.cpp:650 scales thresholdForFTLOptimizeAfterWarmUp (64000 to 256000) and thresholdForFTLOptimizeSoon (1000 to 4000) whenever WTF::numberOfProcessorCores() is at most 4. In Bun that count follows the cgroup CPU quota, so every Graviton small instance and every --cpus<=4 container is included, not only embedded devices. Fix: gate the scaling on the embedded-device case it targets (or skip it under USE(BUN_JSC_ADDITIONS), or set ftlThresholdScaleForFewCores to 1 in Bun's option setup) so server deployments keep the base thresholds.Why this was flagged
Trigger: a Bun process starts on Linux arm64 (not Android) where WTF::numberOfProcessorCores() returns 4 or fewer. Source/WTF/wtf/NumberOfCores.cpp:88-101 takes the minimum of _SC_NPROCESSORS_ONLN, sched_getaffinity and uv_get_constrained_cpu(), so a Kubernetes or Docker CPU limit of 4 or less on a large arm64 host also satisfies the test. Source/JavaScriptCore/runtime/Options.cpp:648-654 multiplies thresholdForFTLOptimizeAfterWarmUp and thresholdForFTLOptimizeSoon by ftlThresholdScaleForFewCores, whose default at Source/JavaScriptCore/runtime/OptionsList.h:441 is 4.0. On the base branch these thresholds stay at their OptionsList.h:453-454 defaults (64000 and 1000). After merging, hot server code in those environments needs four times as many executions before it reaches the FTL, lowering steady-state throughput for the affected deployments. No safeguard offsets this: the option description at OptionsList.h:441 names 'devices', but nothing in the condition distinguishes a device from a quota-limited server, and Bun's own option setup does not reset the scale.
Verification: The block is new in this PR at Source/JavaScriptCore/runtime/Options.cpp:648-654 and is not gated by USE(BUN_JSC_ADDITIONS). overrideDefaults() is called unconditionally from Options::initialize (Options.cpp:1129). Source/WTF/wtf/NumberOfCores.cpp:88-101 takes the minimum of sysconf(_SC_NPROCESSORS_ONLN), sched_getaffinity CPU_COUNT, and uv_get_constrained_cpu().
-
🟡
Source/JavaScriptCore/runtime/JSStringJoiner.cpp:544— Joining a large typed array with a non-Latin-1 separator now throws "Out of memory" for results between 2^30 and 2^31-1 characters, which the base branch produced. JSTypedArrayJoiner stores the result in a Vector<char16_t> whose capacity is capped by maxBufferCapacity at Source/JavaScriptCore/runtime/JSStringJoiner.cpp:544, i.e. (UINT_MAX >> 1) / 2 = 2^30 - 1, so expandBuffer refuses and join() reports OOM once m_length nears that. Fix: let the 16-bit joiner build results up to String::MaxLength like the Latin-1 joiner and the base JSStringJoiner, e.g. by sizing with a StringImpl::tryCreateUninitialized buffer or a byte-counted allocation instead of a char16_t Vector, while keeping the m_length <= String::MaxLength check.Why this was flagged
A caller runs TypedArray.prototype.join with a separator containing a character above U+00FF on a large typed array, reaching genericTypedArrayViewProtoFuncJoin at Source/JavaScriptCore/runtime/JSGenericTypedArrayViewPrototypeFunctions.h:642, which calls joinTypedArray. joinTypedArray picks JSTypedArrayJoiner<ElementType, char16_t> because separator.is8Bit() is false (JSStringJoiner.cpp:709-711). That joiner's maxBufferCapacity is (std::numeric_limits::max() >> 1) / sizeof(CharacterType) (JSStringJoiner.cpp:544), i.e. 2^30 - 1 elements. ensureRoom calls expandBuffer, which returns false when room > maxBufferCapacity - m_length (lines 558-560), and join() turns that into throwOutOfMemoryError. On the base branch the same join went through JSStringJoiner, whose only limit was CheckedInt32 totalLength overflowing at String::MaxLength = 2^31 - 1 (JSStringJoiner.cpp:366-372), so a result of 1.1G to 2.1G UTF-16 characters succeeded. The m_length <= String::MaxLength check in append (line 619) is not what stops it; the Vector capacity cap triggers first for 16-bit output only.
Verification: Triggers when TypedArray.prototype.join is called with a non-Latin-1 separator and the joined result would be between 2^30 and 2^31-1 UTF-16 code units. Source/JavaScriptCore/runtime/JSStringJoiner.cpp:539 defines maxBufferCapacity, for char16_t 2^30-1; expandBuffer at lines 555-558 returns false, and join at 696-697 turns that into throwOutOfMemoryError. The base branch allowed results up to String::MaxLength = 2^31-1.
-
🟡
Source/JavaScriptCore/heap/Heap.cpp:2160— Conditional, debug builds only: a thread that polls the heap without holding heap access, which the fork's own comment at Heap.cpp:2145 says can happen, now aborts on an assertion instead of being handled. The no-arg stopIfNecessarySlow() at Heap.cpp:2133 asserts assertIsAccessHolder() before it reaches the Bun branch at Heap.cpp:2158 that was written for exactly that caller, and that branch then calls collectInMutatorThread(), whose callee asserts access again at Collector.cpp:342. Fix: either drop the no-access accommodation (and its comment) if no such caller remains, or gate the new access asserts on the fork's no-access case so ASSERT_ENABLED builds take the same path release builds do.Why this was flagged
A caller invokes Heap::stopIfNecessary() (HeapInlines.h:256) while m_worldState lacks hasAccessBit; the fork's comment at Heap.cpp:2145-2146 says such callers exist and that their pending epilogue is run on the next acquireAccess(). mayNeedToStop() is true, so stopIfNecessarySlow() runs and at Heap.cpp:2133 executes assertIsAccessHolder(), which under ASSERT_ENABLED checks currentThreadIsAccessHolder() (Heap.cpp:549) and fails because hasAccess() is false. If the thread also holds the conn, the Bun branch at Heap.cpp:2157-2160 calls collectInMutatorThread(), and Collector::collectInMutatorThread() at Collector.cpp:342 and checkIsConductor() at Collector.cpp:1058 assert access again. On the base branch stopIfNecessarySlow() had no access assertion and handled a pending epilogue with handleNeedCollectionEpilogue(oldState) first, so the same caller ran without aborting. Release builds are unaffected because assertIsAccessHolder() is empty there (Heap.h:462).
Verification: Triggers only in ASSERT_ENABLED builds, when an embedder calls Heap::stopIfNecessary() while m_worldState lacks hasAccessBit. The diff adds
assertIsAccessHolder();at Source/JavaScriptCore/heap/Heap.cpp:2133 in the no-argHeap::stopIfNecessarySlow(). So a no-access caller aborts at 2133 before reaching the branch at Heap.cpp:2157-2160 that the same PR wrote for that caller.
|
The four findings are read against the code. None of them is in the merge of
|
main is one commit ahead of the last merge: #1021 (ee59053). One file conflicts, in one place: - runtime/JSMicrotask.cpp: #1021 renames two functions that the switch of runInternalMicrotask() calls. Since WebKit/WebKit@9fadb87996 each case of that switch is a function of its own, and the switch only dispatches. The branch keeps that dispatch. Two changes are in neither parent. Both follow the names of #1021 in code that only this branch has: - runtime/JSMicrotask.cpp: the job of a promise reaction asks AOT::canRunJobHandler(), and the job of a microtask asks AOT::canEnterJobFunction(). They were canRunHandlerOfJob() and canEnterFunctionOfJob(). - runtime/ProxyObject.h: a comment names AOT::RuntimeHooks::proxyDefinePropertyTarget(), which was targetThatProxyDefinesOn(). No other identifier that #1021 removes is left in the tree, and #1021 adds no use of an identifier that this branch removed.
… [skip size check] main now pins ee59053d32 of the fork's main (#48120). The engine of this branch is oven-sh/WebKit#1015 with that commit merged in: WEBKIT_VERSION is the preview build of its head, 2555642f5c. Two files conflict: - scripts/build/deps/webkit.ts: WEBKIT_VERSION. - test/expected-durations.json: main sorted the entries. The entry of aot/harness/where-a-child-is.test.ts goes where the order puts it.
|
A note for the next merge of main into this branch, if #1026 lands first. #1026 deletes the declaration Resolve it with main's side: the declaration stays deleted. If it comes back it has no definition and no caller, so no build and no test fails. |
Conflicts: - runtime/JSMicrotask.cpp: the jobs stay the functions of the upstream dispatch. The two comments of LEAVE_FOR_COMPILED_JOB take the words of main. - runtime/ProxyObject.cpp: the comment describes the cache of the upstream ProxyHandlerOffset, in the words of main. - wasm/WasmStreamingParser.h: NODELETE in front, as upstream writes it, and the span parameter of main. - wasm/WasmOMGIRGenerator.cpp: upstream moved the context switch of an indirect call into the generator of the call. The code for an image of main moves with it: emitPrepareToCageMemoryBase and emitCageMemoryBase around the load of the memory registers, with a scratch register of its own for an image, and the function's record as one more input of the patchpoint.
…he heap's set of blocks and the directory's list have room for it A program built with --aot and run under `ulimit -v` could end with "Segmentation fault at address 0xBBADBEEF" where it has to end with a RangeError or with the FATAL line that names the limit. BlockDirectory::tryAllocateBlock() took a block from the cage and then recorded it with requests for memory that may not fail: MarkedSpace::didAddBlock() adds the block to the heap's set of blocks, whose table doubles (1,179,664 bytes at 32,768 blocks), and BlockDirectory::addBlock() appends it to the list of the directory, which grows by half. Where the limit is used up, bmalloc ends the process. Under `ulimit -v 1048576` the doubling at 32,768 blocks falls where a program that only makes objects has used up the limit. With limited address space MarkedBlockCage::willAddBlock() now runs before MarkedBlock::tryCreate(). It grows the set early and the list when it is full, with requests that may fail. A growth that fails owes nothing and is tried again before the next block. When the set or the list has no room for one more block, no block is made, and LocalAllocator::allocateSlowCase() does what it does where the cage has no block: it collects and tries again, a request that can fail gets null, and a cell that cannot fail ends the process with the FATAL line. The last words name the limit on address space, also for a block of Structures. A directory takes no block from another directory when its list has no room for it. The bits of a directory still grow in addBlock(), now also for a list that grew before its block. This is the shape of MarkedSpace::tryMakeRoomForPreciseAllocation() (#942) for blocks. An owed RangeError for each growth that fails, as willAddSymbol() owes one, was measured and left out: a program that goes on with malloc used up owes it again for each block, and 10 of the 71 cases of Bun's test/aot/heap-limit.test.ts run into their deadline. Still requests that may not fail on this path: the shrink of the set when blocks go (HashTable shrinks on remove), the bits of a directory, MarkedBlock::Handle and the list of free indices. Tests: seven cases in AOTHeapCageTests.cpp. Each fails without its part of the change.
…embered positions when there is no memory for the table Image::positionOf() made its table of 1,024 remembered positions (40,960 bytes) at the first call, with a request for memory that may not fail. The first call is often the one for the stack trace of an uncaught error. When that error is a RangeError for memory that is used up under `ulimit -v`, the request ended the process with "Segmentation fault at address 0xBBADBEEF" in place of the error. The table only saves work. It is now made with a request that may fail, and without it each position is read from the image. Measured with the program of Bun's test "a program that fills what a limit on address space leaves says so" at the limit where this happened (`ulimit -v 1158144` for an executable that is not trimmed): 4 of 360 runs ended so before, 0 of 360 after.
There was a problem hiding this comment.
Additional findings (outside the current diff — GitHub can't attach inline comments there):
-
🔴
Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp:2290— Building an AOT image on x86-64 aborts with "FATAL: no register for %tmp33" for a wasm module whose indirect call passes six integer arguments in BoundsChecking mode; the base branch builds it. WasmOMGIRGenerator.cpp:2290 asks B3 for a scratch for image code in both memory modes, on top of six argument registers, the code pointer pinned to r10, boxedCalleeCallee, calleeInstance and functionInfo, with three wasm registers pinned: one register more than x86-64 has. Fix: take no B3 scratch for an image in BoundsChecking mode; store functionInfo to the callee frame before the context switch and use its register as cageScratch, as commit ab2c0c9 did before the merge dropped it.Why this was flagged
Trigger:
bun build --aotcompiles a wasm function in OMG for an image, in MemoryMode::BoundsChecking, containing call_indirect or call_ref whose signature has six or more i32/i64 parameters. Entry: OMGIRGenerator::emitIndirectCall, WasmOMGIRGenerator.cpp:2167. The one call patchpoint takes the six argument GPRs, calleeCode fixed to r10 (line 2278), boxedCalleeCallee, calleeInstance and functionInfo as SomeRegister (lines 2279-2282), and line 2289-2290 adds numGPScratchRegisters = 1 whenever m_context.codeForImage. x86-64 Air has 13 allocatable GPRs; BoundsChecking pins rbx, r14, r15, leaving 10 for 11 register demands, so the allocator hits its RELEASE_ASSERT and the image build process dies. On the base branch (873ab3a) the context switch was a separate patchpoint with only calleeInstance and one scratch, and the call patchpoint had no scratch, so the same module built. No safeguard: there is no test of an indirect call with six arguments in the image suite, and WASM_DECLINE_FOR_IMAGE_IF only declines tail calls (line 2169).Verification: WasmOMGIRGenerator.cpp lines 2289-2290:
if (m_mode == MemoryMode::Signaling || m_context.codeForImage) patchpoint->numGPScratchRegisters = 1;is new in this diff; the base had no scratch on the call patchpoint. Demand: 6 fixed args + r10 + 3 SomeRegister inputs + one Scratch tmp = 11 distinct registers from 10. The greedy allocator hitsfailOutOfRegisters(AirAllocateRegistersByGreedy.cpp:4685-4706). -
🔴
Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp:2320— Image (AOT) wasm code can store garbage as the callee's import record on a cross-instance call_indirect, which the base branch stored correctly. In emitIndirectCall the functionInfo input (patchArgsIndex + 3, SomeRegister) is consumed at WasmOMGIRGenerator.cpp:2320, after the context switch at 2315 has written wasmBoundsCheckingSizeRegister. OMG image code with memory runs in MemoryMode::Signaling, where that register is not pinned and inputs are early uses, so B3 may place functionInfo there. Fix: consume functionInfo before the switch (move the storePtr above the isSameContextInstance branch) or give it a fixed register the switch never writes, as calleeCode already gets.Why this was flagged
Source/JavaScriptCore/aot/image/AOTWasmModules.cpp:386-403 compiles OMG image code with MemoryMode::Signaling whenever the module has memory and the flavor is Trapping. WasmOMGIRGenerator.cpp:1363-1364 pins wasmBoundsCheckingSizeRegister only in BoundsChecking mode, so in Signaling mode B3 may allocate it to any value. The call patchpoint at 2274 only clobberLate()s wasmPinnedRegisters(), and early-use inputs do not interfere with late clobbers, which is why calleeCode gets a fixed register at 2278. functionInfo is appended with ValueRep::SomeRegister at 2282 and read at 2320, after loadPairPtr at 2315 has overwritten wasmBoundsCheckingSizeRegister on the cross-instance path. On the base branch the context switch was a separate patchpoint emitted before the call patchpoint, and the storePtr of functionInfo ran before any pinned register was written. When the allocator picks wasmBoundsCheckingSizeRegister for functionInfo, the callee frame's codeBlock slot receives the callee's memory size instead of the WasmOrJSImportableFunction record. WasmBBQJIT.cpp:4763-4766 documents that wasm_to_js_wrapper_entry reads that slot as the import record for a JS callee, so a cross-instance indirect call to a JS import dereferences a bogus pointer and crashes.
Verification: Triggers when OMG image code compiled in MemoryMode::Signaling (AOTWasmModules.cpp:386-403, :439) performs a cross-instance call_indirect and B3 assigns the functionInfo input to wasmBoundsCheckingSizeRegister. In Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp, :2315 loadPairPtr overwrites that register, and only afterwards :2320 storePtr consumes functionInfo; the base branch consumed it with no intervening write.
… defers the collection of the request that fails "heap-cage/cage/directory-takes-no-block-that-its-list-has-no-room-for" failed on the Linux lanes of CI: the request for a cell did not fail. The test let that request collect. Where the list of the directory has no room, BlockDirectory::tryAllocateBlock() makes no block, and LocalAllocator::allocateSlowCase() then collects and tries again. That collection gives memory back to malloc, and with it the list can grow. Whether it does depends on the machine. The request now runs with collection deferred, as in the other tests that take the large pieces of malloc. The test also checks that the other directory keeps its blocks. Without the check in LocalAllocator::tryAllocateWithoutCollecting() the test still ends in BlockDirectory::addBlock() with SIGSEGV.
…ounds of an AOT executable [skip size check] The engine has main of the fork at oven-sh/WebKit#1025 and three more commits: a block of the heap is made only once its records have room under a limit on address space, a position in the source is found without the table of remembered positions when no memory is left for it, and a test of the first. A trimmed hello world maps 26,351,648 bytes and an untrimmed one 68,847,648 (25,975,112 and 68,430,152 on main).
…f the boxed callee to cage the memory base The merge of main at #1025 (e50312b) gave the patchpoint of an indirect call one register more than x86-64 has. Upstream switches to the callee's instance inside the generator of the call, so the patchpoint has the code pointer in a fixed register and the boxed callee and the callee instance in two more. Code for an image added the function's record as an input and a scratch register of its own, for the base of the cage that it loads before the switch. With six arguments in registers only three registers are free there, and Air stopped with "FATAL: no register for %tmp64". Bun's test/aot/parallel/webassembly/six-arguments-through-a-table failed so on every x64 lane. The scratch of code for an image is now the register of the boxed callee. That value is stored into the callee's frame at the start of the generator and is dead from there, as the callee instance is dead behind its store where upstream reuses it. The function's record is stored at the start too. Signaling mode keeps its scratch register: there an input can lie in the register of the bounds-checking size.
…arguments A module without a memory whose function calls through its table with six arguments. On x86-64 every register is taken where that call is made. With the patchpoint as the merge of main at #1025 first had it, the compiler stops there with "FATAL: no register", and this test fails.
There was a problem hiding this comment.
Nothing blocking. The comments below are optional suggestions. There is no need to push a fix for them before merging.
Beyond the inline finding, I also checked the new OMG indirect-call change in Source/JavaScriptCore/wasm/WasmOMGIRGenerator.cpp (emitIndirectCall, around line 2307): reusing the boxed-callee register as the cage scratch for image code is sound, since that register is dead after storeWasmCalleeToCalleeCallFrame and the existing ASSERTs still exclude the pinned registers and the live code pointer.
Extended reasoning...
This run covers the fork's merge-up of upstream WebKit plus Bun-specific JSC commits (AOT, heap cage, JSON.stringify, OMG/BBQ wasm calls); the diff is about 19,500 files. The only commit new since the previous review that changes runtime code is the OMG indirect-call scratch-register fix, which was read and ruled out as a register-overlap hazard; the inline finding already signals that a human look is needed.
Additional findings (outside the current diff — GitHub can't attach inline comments there):
-
🟣
Source/JavaScriptCore/runtime/JSObject.cpp:896— Pre-existing, partial fix: in AOT-compiled code a sloppy-mode store through a forwarding proxy on a locked built-in still throws a TypeError, while the same store with an interpreted handler is now ignored. lookedThroughForwardingProxy at JSObject.cpp:896 is computed before the AOT hook at JSObject.cpp:898 swaps receiver for the proxy's target, so it stays false for a compiled handler. Fix: judge every store the walk takes through a forwarding proxy the same way, whether the proxy was skipped by receiverForDefinePropertyOnReceiver or by proxyDefinePropertyTarget, e.g. compute lookedThroughForwardingProxy after the ENABLE(AOT) block as well.Why this was flagged
Trigger: in a realm that locks its built-ins, compiled (AOT) code runs
const p = new Proxy(Math, {}); p.foo = 1;in sloppy mode, where the handler literal{}is an AOT::Object (CompiledObjectType). The store reaches JSObject::definePropertyOnReceiver (JSObject.cpp:880). ProxyObject::forwardsOwnPropertyDefinitionToTarget returns false for a compiled handler (ProxyObject.h:291-294), so receiver stays the proxy and lookedThroughForwardingProxy at JSObject.cpp:896 is false. Then AOT::RuntimeHooks::proxyDefinePropertyTarget (AOTObjectMethodTable.cpp:1087-1116) returns proxy->target(), and JSObject.cpp:898-899 sets receiver = Math. At JSObject.cpp:904-908 Math's immutable-property policy applies with throwsInSloppyMode, so shouldThrow is true and definePropertyOnReceiverSlow throws a TypeError. With an interpreted{}handler the walk skips the proxy, lookedThroughForwardingProxy is true, and the store is silently ignored, which is the behavior commit 768023a declares correct. The base branch throws on this AOT path too, so this is pre-existing; the PR's fix only covers the non-AOT route.Verification: pre-existing. JSObject.cpp:896
lookedThroughForwardingProxyis false for a compiled handler (ProxyObject.h:294-295 returns false forCompiledObjectType). Only afterwards, line 898AOT::RuntimeHooks::proxyDefinePropertyTargetswapsreceiverto the locked target. Line 904-908: shouldThrow=true -> TypeError, while the interpreted-handler path is silently ignored. On the base commit the same AOT path also threw.
Two commits more than 4f16020e72: an indirect WebAssembly call in code for an image no longer asks for a register that x86-64 does not have (test/aot/parallel/webassembly/six-arguments-through-a-table failed on the x64 lanes), and a test of that in the engine.
main is at #1028 (d837f04). Conflicts: - heap/SlotVisitor.cpp, heap/Collector.cpp: #1028 and this branch each made the collector thread mark where a collection of compiled code has no helper thread. #1028 adds Collector::startsHelpersLazily() to the condition under which drainInParallelPassively() marks itself. Upstream moved that condition into Collector::runConcurrentPhase(), so the term of #1028 goes there. The change of 3b77c53 in drainInParallelPassively() has nothing left to decide and is removed: the function is upstream's again. - aot/tests/AOTCollectorTests.cpp: the test of #1028 and the test of 3b77c53 both stay. CollectorPause of #1028 gets a third value for the options of the second one. - assembler/MacroAssembler.h, MacroAssemblerARM64.h and MacroAssemblerX86_64.h: #1028 corrects operations that upstream corrected in WebKit/WebKit@40aa4a427250: a blinded addition, or32() of an immediate to an address, branchTest64() with the mask INT32_MIN, test32() and branchTest32() with a condition on the sign. The code is upstream's. What only #1028 has stays: generateTest32() does not narrow a test to one byte at an offset that would overflow. - assembler/ARM64Assembler.h: #1028 removes fmov_top(), whose size bits were wrong. Upstream corrected the bits and checks the encoding in testmasm, so the function stays. - b3/B3ReduceDoubleToFloat.cpp: isExactInDouble() of #1028 in front of a function that upstream marks NODELETE. - aot/facts/AOTUnitedFamilies.h: #1028 reads and writes the parents through a pointer, with WTF::atomicLoad() and WTF::atomicStore() in the form that upstream removed. The order is a template argument. - wasm/WasmOMGIRGenerator.cpp: #1028 puts a path in front of the context switch of an indirect call, for code that restores the pinned registers after the call. Upstream moved that context switch into the generator of the call, so the new path stands in front of the call patchpoint and the block of the old context switch stays removed.
Problem
mainsince AOT: replace the flow passes and the B3 back end with a scan, a link and one walk #997, and upstream landed 611 more.Fix
5a61071f79, then upstream8156ba68efab, thenmain. Land this as a merge commit, not a squash, and only after AOT: stack traces as in bun run, code from disk, workers, embedded files, module mocks, build cost bun#48478 is on Bun'smain(Notes).a9060539a4withoutmain: 76 lanes and 7 test jobs each (Notes).Background
WTF::HashTablekeeps one status byte for each slot (WebKit/WebKit@53bedf6450). A slot that was never filled is not initialized.emitFindSparseElement()is assembly of the AOT run time. It searches the table of aSparseArrayValueMapwithout a call.fs.read()while JavaScript runs. JavaScriptCore assumes that only shared buffers change.Downsides
Options::alwaysUseSharedArrayBufferandHeap::hasAccess().BUN_JSC_useSharedArrayBufferno longer exists.join()of an integer typed array keeps to one pass. Upstream measured 10.1x for two passes and 7.3x for one (Uint8Array).JSON.stringifyof one small object takes 14% more instructions than before the merge, a list of objects 39% fewer (Notes). Upgrade to upstream WebKit 1d4bed41aca8 #992's two questions are still open (Upgrade WebKit to 1d4bed41aca8 bun#47811).Notes
How the branch is made
e7e711f9d009e949d324: upstream1d4bed41aca8and fourteen fork commits) merged onto5a61071f79, the commit that Bun'smainpinsa19f28c2b28156ba68efabmergedcdda0c7916toa9060539a42f97fc86b0mainmerged at #1008, two commits ahead of what Bun'smainpinned then (#1001 and #1008)2555642f5cmainmerged again at #1021 (ee59053d32)e50312b797mainmerged again at #1025 (873ab3a426), the commit that Bun'smainpins nowff06eb7645to6f0282e86btest/aot/heap-limit.test.ts(rows 13 to 15 below) and two for the merge of step 6 (rows 16 and 17)5c5241eeb8mainmerged again at #1028 (d837f045a2)mainwith this merged needs two changes in Bun: the Bun side of the upgrade (Upgrade WebKit to 8156ba68efab bun#48297) and the Bun side of AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 (AOT: stack traces as in bun run, code from disk, workers, embedded files, module mocks, build cost bun#48478). Upgrade WebKit to 8156ba68efab bun#48297 builds only on a Bunmainthat has AOT: stack traces as in bun run, code from disk, workers, embedded files, module mocks, build cost bun#48478. AOT: stack traces as in bun run, code from disk, workers, embedded files, module mocks, build cost bun#48478 pins a preview of AOT: a sum of two values tests both of them for int32 #1030, which is open. If this pull request lands before AOT: a sum of two values tests both of them for int32 #1030, every build with AOT: a sum of two values tests both of them for int32 #1030 has the upgrade too, and neither Bun pull request can land alone. The order: AOT: a sum of two values tests both of them for int32 #1030 lands and AOT: stack traces as in bun run, code from disk, workers, embedded files, module mocks, build cost bun#48478 pins its build and lands. Then this branch mergesmainagain (AOT: a sum of two values tests both of them for int32 #1030 does not conflict with it), Upgrade WebKit to 8156ba68efab bun#48297 merges Bun'smainand pins the preview of this head, and when its CI passes this pull request lands, with Upgrade WebKit to 8156ba68efab bun#48297 right behind it.robobun/99893ae1/upgrade-to-8156ba68efab-bun-main-engineis this branch without steps 4 and 5. Upgrade WebKit to 8156ba68efab bun#48297 pinned a build of it while Bun'smainhad the Bun side of AOT: more fixes, stacked on #999 #1000 only. The Bun side of AOT: the next base #1001, AOT: fixes after #1001: three places in aot/facts, a build that doubled, module mocks #1008 and AOT: compiler and module loader fixes; tests that need Bun built-ins move to Bun #1021 is on Bun'smainnow (AOT: the next base bun#48120), and Upgrade WebKit to 8156ba68efab bun#48297 pins the preview build of6f0282e86b. Bun needs the Bun side of AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 (AOT: stack traces as in bun run, code from disk, workers, embedded files, module mocks, build cost bun#48478, open) to build this head.WTF::atomicLoad(). The commit message lists the others.runtime/AbstractModuleRecord.h,aot/object/AOTObjectMethodTable.cpp,heap/MarkedBlockCage.cppandaot/tests/AOTCollectorTests.cpp. The commit message says how each is resolved.whatTableSaysOf()inaot/facts/AOTLinkCalls.cpp, new in AOT: fixes after #1001: three places in aot/facts, a build that doubled, module mocks #1008, calledWTF::atomicLoad()andWTF::atomicStore()with astd::memory_order. Since WebKit/WebKit@6ab0aebc81bc the order is a template argument, so the merge did not compile without the change.aot/tests/AOTCollectorTests.cpp: AOT: fixes after #1001: three places in aot/facts, a build that doubled, module mocks #1008 gives the processes of the collector tests pauses of 10 s, so that a collection marks with the mutator stopped. The test of3b77c53c69(a collector thread that marks beside a running mutator) keeps the pauses of a program. With the long pauses no collection reaches its concurrent phase: a release build without the change of3b77c53c69passes the test in 40 of 40 runs. With the pauses of a program its process does not end in 7 of 40 runs.heap/MarkedBlockCage.cpp: AOT: fixes after #1001: three places in aot/facts, a build that doubled, module mocks #1008 prints every literal oflogExhaustion()by its characters. The merge takes that text, which covers row 10 below.runtime/JSMicrotask.cpp. AOT: compiler and module loader fixes; tests that need Bun built-ins move to Bun #1021 renames two functions that the switch ofrunInternalMicrotask()calls. Since WebKit/WebKit@9fadb87996 each case of that switch is a function of its own, so the branch keeps its dispatch. The two calls get their new names where they are now:AOT::canRunJobHandler()andAOT::canEnterJobFunction(). A comment inruntime/ProxyObject.hfollows the rename toproxyDefinePropertyTarget(). No other identifier that AOT: compiler and module loader fixes; tests that need Bun built-ins move to Bun #1021 removes is left in the tree, and AOT: compiler and module loader fixes; tests that need Bun built-ins move to Bun #1021 adds no use of an identifier that this branch removed.runtime/JSMicrotask.cppandruntime/ProxyObject.cpp: AOT: WebAssembly in the optimizing tier, arm64 branch islands, fixes and new names #1025 rewords comments beside code that upstream changed. The code stays upstream's and the comments take AOT: WebAssembly in the optimizing tier, arm64 branch islands, fixes and new names #1025's words.wasm/WasmStreamingParser.h: upstream'sNODELETEin front and AOT: WebAssembly in the optimizing tier, arm64 branch islands, fixes and new names #1025'sstd::spanparameter.wasm/WasmOMGIRGenerator.cpp: upstream moved the context switch of an indirect call into the generator of the call (WebKit/WebKit@8156ba68efab range), and AOT: WebAssembly in the optimizing tier, arm64 branch islands, fixes and new names #1025 makes OMG write code for an image. The merge puts AOT: WebAssembly in the optimizing tier, arm64 branch islands, fixes and new names #1025'semitPrepareToCageMemoryBase()andemitCageMemoryBase()around the load of the memory registers in that generator, and the function's record is one more input of the patchpoint. Code for an image loads the base of the cage while the callee instance is still needed, so it cannot use that register as its scratch, as upstream does. The merge first gave it a scratch register of its own, which x86-64 does not have there (row 16). It takes the register of the boxed callee now.Source/JavaScriptCore,Source/WTFandSource/bmallocwere looked for in the merged tree.heap/SlotVisitor.cpp: a collection of compiled code that has no helper threads waited for helpers. AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 addsCollector::startsHelpersLazily()to the condition under whichdrainInParallelPassively()marks itself. Upstream moved that condition intoCollector::runConcurrentPhase(), so the term of AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 goes there. This branch's change for the same hang (3b77c53c69, indrainInParallelPassively()) has nothing left to decide and is removed.aot/tests/AOTCollectorTests.cppkeeps the test of AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 and the test of3b77c53c69.assembler/MacroAssembler.h,MacroAssemblerARM64.handMacroAssemblerX86_64.h: AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 corrects a blinded addition,or32()of an immediate to an address,branchTest64()with the maskINT32_MIN, andtest32()andbranchTest32()with a condition on the sign. Upstream corrected the same operations in WebKit/WebKit@40aa4a427250. The code is upstream's, and the tests of AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 intestmasmstay. What only AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 has also stays:generateTest32()does not narrow a test to one byte at an offset that would overflow.assembler/ARM64Assembler.h: AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 removesfmov_top(), whose size bits were wrong. Upstream corrected the bits and checks the encoding intestmasm, so the function stays.b3/B3ReduceDoubleToFloat.cpp(a helper of AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 in front of a function that upstream marksNODELETE),aot/facts/AOTUnitedFamilies.h(AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 callsWTF::atomicLoad()andWTF::atomicStore()in the form that upstream removed) andwasm/WasmOMGIRGenerator.cpp. There AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 puts a path for code that restores the pinned registers after a call in front of the context switch of an indirect call. Upstream moved that context switch into the generator of the call, so the new path stands in front of the call patchpoint.heap/Collector.cpp. Of the 204 identifiers that AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 removes, onlyfmov_topis left in the tree, and AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 adds no use of an identifier that this branch removed.ab2c0c92fe(OMG and code for an image) has nothing left to apply to: since AOT: replace the flow passes and the B3 back end with a scan, a link and one walk #997 an image gets its WebAssembly code from BBQ.The merge of upstream
8156ba68efabLEGACY_NODELETEasNODELETE(WebKit/WebKit@1aa812de0e) beside a line that the fork changed. The fork's lines are respelled the same way. For the 77 lines that upstream also has, the result is upstream's line, character for character.a19f28c2b2says what each of the other files takes.1d4bed41aca8against the branch) and after it (8156ba68efabagainst the result) were compared as sorted lists of changed lines, without white space and without the two spellings ofNODELETE. 370 of 390 are the same. The other 20:assembler/MacroAssemblerARM64.hbranchAdd64,branchSub64), so the fork's helpermoveSignExtendedToCachedReg()is gone.branchTest64()keeps the fork's choice of a register and not upstream's assertionassembler/MacroAssemblerX86_64.cpp,.h,assembler/testmasm.cppCPUFeatureSet(below).test32()has upstream's condition argumentb3/B3Procedure.cpp,b3/B3SwitchValue.cpp,b3/air/testair.cppb3/air/AirAllocateRegistersByGreedy.cppftl/FTLLowerDFGToB3.cppPutByValclobber the floating point scratch register on every CPU, as the fork had it. Upstream does so on x86-64heap/Heap.cpp,heap/MarkedBlock.cpphasAccess()andassertMayAccessBitsUnlocked()for the two names that upstream removedinterpreter/Interpreter.cpp,runtime/StackFrame.cpp,.hStackFrame::appendTo()now. The fork's version stays, which also writes the frames of compiled codejit/AssemblyHelpers.cpp,wasm/js/JSToWasm.cppmaterializeTagRegistersIfNeeded()is gonellint/LowLevelInterpreter64.asmruntime/JSONObject.cppyarr/YarrPattern.cpp,wtf/URLParser.cppURLParser.cppkeeps the fork'sgrow()What upstream rewrote under the fork
WTF::HashTable(WebKit/WebKit@53bedf6450). The fork's additions wrote the old layout and compiled only in part:tryAllocateTable(),tryExpand()andprefetchForHash()follow the status bytes (cdda0c7916).testaot native heap-cagehas the tests oftryReserveCapacityForAdd(): 44 passed.emitFindSparseElement()took the mask from the table's header and told an empty slot by a flag in the slot. It reads the status byte first now, with the same three registers (f6270cf42a). The count of probes lives in the upper half of the index register while the search runs.testaot native sparse-elementspasses on x64 and, in CI, on arm64.CPUFeature::F16C, found bycollectCPUFeatures()where AVX is usable, and asked throughsupportsFloat16(CPUFeatureSet). Upstream's four new tests intestmasmask the host's set.JSON.stringify(WebKit/WebKit@aeca1a989f). Upstream's table of prepared structures is in.appendPreparedObject()andappendUnpreparedObject()count their level with the fork'senterHolder()andleaveHolder(). Upstream's lengths of the last results choose the first buffer, then the fork's hints choose as before. A differential test of 9,000 random values against the general path (a replacer function) found no difference, with outputs of up to 6.9 MB.JSON.parse(WebKit/WebKit@c8e6298f1a, WebKit/WebKit@d24e80edb5). Upstream's loop over the objects of an array, with the fork's seven changed lines in it. For this file the fork's difference from upstream is the same before and after.-Wthread-safety.What the review of the merged tree found
After the merge compiled, each of the 208 upstream commits was read against the fork's code for two things: fork code that relies on a contract that the commit changed, and new upstream code that goes around a rule of the fork. A second reader tried to refute each finding. Eight held.
JSON.parseasked once an array, and no longer once an object, whether an out-of-memory error is owed. A long array of flat objects in a program with a full cage ended the process where it threw before. Reached throughResponse.json()andBun.JSONL, which have no AOT parser in front06f505b41cJSON.stringifybehind two long ones kept a buffer of their length: upstream shrinks only a result of more than 1024 characters9dbbc11051appendPreparedObject()wrote{}for a prepared structure without properties before it counted the level3092ec58c1return_call_indirectorreturn_call_refwas refused for an image, and its module with it589b7f1467testmasm: the fork'stestLinkedSites()expected a test-bit branch over 16 KB to keep its nop. Upstream compacts up to 32 KB now. arm64 only3e040cd719testaot native locked-realm/typed-arrays-...expected an object below a typed array to take a store past its end. Upstream's typed arrays intercept from the startb2e20ddd46Heap::releaseAccessSlow()conducts a collection where no collector thread can be made. Upstream'sreleaseAccess()has cleared the debug record of who has access by then, so a build with assertions aborted there837692a987joinIntegerTypedArray()reads every element twice and stops the process when the two passes differ (WebKit/WebKit@d336a98ee3). A pendingfs.read()of Bun writes the array from another thread. A debug build of Bun aborted in the first or second round of a 4 MB read withASSERTION FAILED: result.ec != std::errc::value_too_large, and a build without assertions hasRELEASE_ASSERT(data.empty())48b4e6f1179ffd31b24band passes with this one.JSGlobalObject::typedArraysInterceptIndexedStores()has nothing left to decide after 6. It stays for whoever owns the locked realms to remove.What CI and the measurements found
testmasm.cpp: the fork'scheckEncodingsFollowPolicy()called the form oftest32()without a condition, which upstream removed on x86-64 (WebKit/WebKit@40aa4a4272). Only the two x64 lanes that build the test programs compile it, and no local build had4766280b08MarkedBlockCage::logExhaustion()wrote the lineFATAL: out of memory. The limit on address space ...through aPrintStream, which makes aCStringof anASCIILiteral. With nothing left to allocate from, that crashed in the middle of the line. Bun'stest/aot/heap-limit.test.tsfailed on x64 withpanic: Segmentation fault at address 0xBBADBEEF. The defect is older than the merge: a build of Bun from before it has the same output on one lane2cdf62b8deJSON.stringifywrites. The record pays from the third object of a structure on. One object with five numbers took 37% more instructions than before the mergebb8fe204eeappendContentOfLongString()asks for six times a piece before it writes it. A long result that ends in a long string grew to twice its length and was copied twice in every call: 26% more cycles for a list of 2,000 stringsa9060539a4BlockDirectory::tryAllocateBlock()took a block from the cage and then recorded it with requests for memory that may not fail: the heap's set of blocks doubles its table (fastMalloc(0x120010)at 32,768 blocks), and the directory's list of blocks grows by half. Underulimit -v 1048576that doubling falls where a program that only makes objects has used the limit up. Bun'stest/aot/heap-limit.test.ts("a program that fills what a limit on address space leaves says so") ended withpanic(main thread): Segmentation fault at address 0xBBADBEEFon debian 13 x64 in 2 of 6 builds of oven-sh/bun#48297.mainmakes the same request (zeroedMalloc(0x100010)), so the defect is older than the mergeff06eb7645AOT::Image::positionOf()made its table of 1,024 remembered positions (40,960 bytes) at its first call, with a request that may not fail. When the first call is for the stack trace of an uncaughtRangeError: Out of memory, that ended the process with the same panic in place of the error. It showed with row 13 out of the way: 4 of 360 runs at the limit where it happense14907f158heap-cage/cage/directory-takes-no-block-that-its-list-has-no-room-forlet the request that has to fail collect. On the Linux lanes of CI that collection gave memory back to malloc, the list grew, and the request did not fail. The request now runs with collection deferred4f16020e72FATAL: no register for %tmp64, and Bun'stest/aot/parallel/webassembly/six-arguments-through-a-tablefailed on every x64 lane (build 139948). The scratch is now the register of the boxed callee, which is dead behind its store at the start of the generator, as the callee instance is where upstream reuses it. Signaling mode keeps its scratch register14ba2d076awebassembly-image/indirect-call-with-six-arguments-has-codedoes: a module without a memory whose function calls through its table with six arguments. With the patchpoint of row 16 before its fix the test ends with thatFATALline6f0282e86bappendUnpreparedObject()meets its structure the second time.JSTests/stress/json-stringify-when-a-structure-is-prepared.jsholds the fast path against the general one around that rule.hasRemainingCapacitySlow()gives a result like the last, an eighth of the length and six pieces, and no more than the length, so thatresult()keeps the buffer.MarkedBlockCage::willAddBlock()now runs beforeMarkedBlock::tryCreate(). It grows the set early (MarkedBlockSet::tryGrowEarly(), at an eighth of the capacity before the table is full, asWeakGCMapdoes) and the list when it is full (BlockDirectory::tryMakeRoomForBlock()), with requests that may fail. A growth that fails owes nothing and is tried again before the next block. When the set or the list has no room for one more block, no block is made, andLocalAllocator::allocateSlowCase()does what it does where the cage has no block: it collects and tries again, a request that can fail gets null, and a cell that cannot fail ends the process with theFATALline. The last words name the limit on address space also for a block of Structures. A directory takes no block from another directory when its list has no room for it. This isMarkedSpace::tryMakeRoomForPreciseAllocation()(AOT: per-global program state, mockable exports, heap-allocated generator frames, bug fixes #942) for blocks.RangeErrorfor each growth that fails, aswillAddSymbol()owes one. Measured, a program that goes on with malloc used up owes it again for each block, and 10 of the 71 cases ofheap-limit.test.tsrun into their deadline. Without it all 71 pass. A change of the test alone was not taken: the case makes one run, so a run that crashes would assert nothing.ulimit -v 1125376, 240 runs each: 22 crashes before, 0 after.ulimit -v 1158144, 360 runs each: 33 before, 0 after. In the LTO build that Bun's CI makes: 10 of 120 atulimit -v 1054720before, and after 0 of 360 at 1054720, 1055744 and 1087488, and 0 of 414 over 69 limits from 1040384 to 1110016 (4 before). The other endings after the change, of those 414: theFATALline 223, theRangeErrorwith the sentence 190, the plainRangeError1.HashTableshrinks on remove, and a set that grew early shrinks again after 11% of the blocks go, was 33%), the bits of a directory (subspace()->didResizeBits()andm_bits.resize()stay one step inaddBlock(), now also for a list that grew before its block),new MarkedBlock::Handle,m_freeBlockIndices.append(), and the list and set of precise allocations outsideCompleteSubspace.aot/tests/AOTHeapCageTests.cpp. Each fails when its part of the change is taken out: the set (five cases fail), the list (two), the check before a directory takes a block (one, with the crash inBlockDirectory::addBlock()underLocalAllocator::tryAllocateWithoutCollecting()), the sentence for Structures (one, it prints the sentence of the Structure heap), the bits (the case of the bits and five more).tryFastZeroedMalloc()now, and without it each position is read from the image.CI
e3b35cd13a, the first head4766280b08, withoutmain670c186d8a, withmainbb8fe204ee, withoutmaina9060539a4, withoutmain8a6bc88536, withmainbefore #10082f97fc86b0, withmainat #10082555642f5c, withmainat #1021e14907f158, withmainat #10254f16020e72, withmainat #10256f0282e86b, withmainat #10255c5241eeb8, this head, withmainat #10288a6bc88536the lanelinux-amd64-lto-hardenedneeded a second attempt: the first stopped indocker/setup-buildx-action, before the build.lto,lto-aot,lto-hardened-aot) and arm64 (those andlto-hardened). Each has more than 125,000 runs of the JavaScriptCore stress tests with 0 failures, andtestFFI,TestWTF,testmasm,testairandtestb3pass.testaotwithoutmain: 4323 passed, 0 failed, 16 todo on x64 (lto-aot), 4307 passed on arm64. Withmainbefore AOT: fixes after #1001: three places in aot/facts, a build that doubled, module mocks #1008, at the first head on arm64: 5057 passed, 0 failed, 17 todo. 19 tests are left out in each of those runs, as expected. AOT: fixes after #1001: three places in aot/facts, a build that doubled, module mocks #1008 makes that list 25. Withmainat AOT: fixes after #1001: three places in aot/facts, a build that doubled, module mocks #1008, at2f97fc86b0: 5217 passed on x64 and 5201 on arm64 (lto-aot), 0 failed, 46 and 17 todo, 25 left out. AOT: compiler and module loader fixes; tests that need Bun built-ins move to Bun #1021 moves the tests that need Bun's built-ins to Bun. Withmainat AOT: compiler and module loader fixes; tests that need Bun built-ins move to Bun #1021, at this head: 4674 passed on x64 and 4658 on arm64 (lto-aot), 0 failed, 46 and 17 todo.e14907f158the twolto-aottest jobs failed in one test, the new one of row 15. Everything else passed there: 4658 of 4659 on x64 and 4642 of 4643 on arm64.testaotat4f16020e72, withmainat AOT: WebAssembly in the optimizing tier, arm64 branch islands, fixes and new names #1025: 4659 passed on x64 and 4643 on arm64 (lto-aot), 4662 and 4645 (lto-hardened-aot), 0 failed, 46 and 17 todo.testaotat this head, withmainat AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028: 4698 passed on x64 and 4682 on arm64 (lto-aot), 4701 and 4684 (lto-hardened-aot), 0 failed, 46 and 17 todo. The JavaScriptCore stress tests have 0 failures in each of the seven test jobs.bb8fe204ee(Upgrade WebKit to 8156ba68efab bun#48297, build 139108): 183 jobs passed, and none failed but the size check. The tests of darwin x64 did not start: that queue is hours behind.Speed and size against
autobuild-5a61071f79The
jscshells of the x64lto-aotlane,autobuild-5a61071f79against the build ofa9060539a4, on one AMD EPYC machine that ran nothing else. User-mode instructions and cycles of the whole process fromperf_event_open, medians of 5 runs in turn. Runs of one binary differ by at most 2.1% in their instructions.JSON.stringifyof one object with a nested object and an arrayJSON.stringifyof{ a: 1, b: 2, c: 3, d: 4, e: 5 }JSON.stringifyof a list of three such objectsJSON.stringifyof a list of 2,000 objects of one shapeJSON.stringifyof a list of 2,000 objects of 40 shapesJSON.stringifywith an indentJSON.stringifyof 2,000 stringsJSON.parseof a list of 2,000 objectsJSON.parseof 25,000 numbersJSON.parseof one small objectjoin()ofUint8Array,Int32ArrayandFloat64ArrayJSON.stringify(12345)+8.7%,JSON.stringify({})+18.5%. For one object with five numbers: 151 instructions of 1,055, about 30 cycles.bb8fe204eerows 1 and 2 were +31.5% and +37.4%. Beforea9060539a4row 7 had 26% more cycles than the old build.JSON.parseof one small object: +2.1% instructions. Upstream rewrote the parser's loops for lists of objects (WebKit/WebKit@c8e6298f1a). Not looked into further.jsc: text 53,673,261 to 54,439,269 bytes (+766,008, +1.43%). By symbols: the instantiations ofWTF::HashTable+137 KB,JSTypedArrayJoiner+127 KB less 45 KB of the oldjoin(), the DFG +110 KB,FastStringifier+56 KB.bun-linux-x64+624 KB).Verified locally
Debug with ASAN, Linux x64, in Bun's build graph with the sources of Bun's
main. On the branch withoutmain.The head with
mainat #1021 (2555642f5c) builds in that graph with the sources of oven-sh/bun#48297 atce3b64c79c, which has Bun'smainwith oven-sh/bun#48120 merged in:bun-debugbuilds.test/js/bun/jsc/webkit-upgrade-8156ba68ef.test.ts(21 tests), and the tests of stores that end in a definition incapture-stack-trace.test.js,web-globals.test.js,vi-utils.test.tsandnode-module-module.test.js.test/aot/parallelbuild with--aotand print what plain Bun prints: the four that Upgrade WebKit to 8156ba68efab bun#48297 adds or changes, and 16 picked across the folder.The heads with
mainat #1025 (e14907f158to6f0282e86b) build in that graph (Release, Linux x64, no LTO) with the sources of oven-sh/bun#48297 ata4199acd54, which has Bun'smainwith oven-sh/bun#48436 merged in:testaot native heap-cage: 63 passed (56 before the seven new cases).test/aot/heap-limit.test.ts: 71 pass, 0 fail. The same with the LTO build ofe14907f158that Bun's CI downloaded.rdx=0x120010):bmalloc::api::mallocunderHashTable<MarkedBlock*>::expand,MarkedBlockSet::add,MarkedSpace::didAddBlock,BlockDirectory::tryAllocateBlock,LocalAllocator::allocateSlowCase.This head was not built locally: it needs the Bun side of #1028 (oven-sh/bun#48478), and the test machine had too little processor time for a build of the engine. Checked in its place, on Linux x64:
assembler/testmasm.cpp, compile with the flags of Bun's build graph.testaotthat CI built of this head (bun-webkit-linux-amd64-lto-aot):collector31 passed,heap-cage63 passed,webassembly-image15 passed. The two tests of a collection without helper threads,collector/helpers/collector-thread-marks-without-themof AOT: faster loops, async code and WebAssembly, smaller executables, stack traces as in bun run #1028 andcollector/helpers/collector-thread-marks-beside-a-running-mutator-without-themof3b77c53c69, pass in 30 of 30 runs each. Without a correction the second one did not end in 7 of 40 runs.The head with
mainat #1008 (2f97fc86b0) did not build in that graph: it needed the Bun side that was still in oven-sh/bun#48120. It was built by itself as the Dockerfile builds a lane (CMake, Release with assertions, Linux x64, no LTO, no mimalloc):jscandtestaotbuild at2f97fc86b0.testaot all: 5205 passed, 0 failed, 17 todo, 25 left out. The list ofAOTNativeTestsOfHostEntries.inchas 25 entries.JSTests/stresswithshift,splice,pristine,symbol,bun-aot,regexp-runsorjson-stringify-whenin their name: 214 pass and one is skipped by its header.On the branch without
main:jsc,testaot,testmasm,testair,testb3,testFFIandbun-debugbuild.a9060539a4: the 95 files ofJSTests/stresswithjsonorstringifyin their name (93 pass, one needs more than the 900 s of the run, andjson-stringify-executing-in-reserved-zone.jsfails as it does with thejscofautobuild-5a61071f79),testaot native heap-cage(44 passed), and a differential run of 8,400 random values throughJSON.stringifyagainst the general path.testmasm: 466 tests pass.testair,testb3andtestFFI(1,509,957 checks) pass (4766280b08).testaot native: 581 passed, 0 failed in the groupscollector,heap-cage,json,locked-realm,slot-exit,stub,hashand one tenth of the rest (48b4e6f117).JSTests/stresswithjsc: 186 files at9ffd31b24b(the 129 that upstream added or changed, and the fork'sbun-*,json-*,*sparse*and*float16*), and 600 more picked at random at4766280b08. 774 pass. The other 12 are skipped by their header, must crash, fail the same with thejscofautobuild-5a61071f79, need the harness (its time zone, or one of two option lines), or need more than the 600 s of the run in this build (threeop_*files).bun build --compile --aot) that uses what upstream changed in C++ prints what plain Bun prints: parameter defaults, a typed array in the prototype chain,join()of every kind of typed array,JSON.stringifyandJSON.parseof lists of objects and of class instances, calls with a spread argument, Float16, sparse arrays, maps and sets.JSTests/stress/bun-aot-builtins-table.jsprints nothing, and Bun'stest/aot/builtins/own-properties.test.tspasses: the table of built-ins agrees with the engine.Differences that stay
join()of an integer typed array with a separator outside Latin-1 throws an out-of-memory error for a result of 2^30 characters or more. Upstream has that limit for float arrays and shared arrays, which takejoinTypedArray(). The fork sends integer arrays there too (48b4e6f117).WTF::numberOfProcessorCores()also follows the CPU limit of a container, so a limit of four or fewer counts. The scale is applied before any option is read: the old values come back withthresholdForFTLOptimizeAfterWarmUp=64000andthresholdForFTLOptimizeSoon=1000, and not withftlThresholdScaleForFewCores=1.Open from #992
onmessage(the rule ofdcaba855fcandfec01eb589), and does the fork keep upstream's atomic weak handles (WebKit/WebKit@5edecbf3e9). This branch carries Upgrade to upstream WebKit 1d4bed41aca8 #992's choice for both: the rule stays, and the weak handles are upstream's.Reflect.defineProperty()answersfalse, andObject.defineProperty()and a class field return without aTypeError, as a store does. This branch does not change that.main) changes the arm ofJSObject::definePropertyOnReceiverSlow()that the upstream merge rewrote, so the two conflict inruntime/JSObject.cpp(lines 863 to 867 here). This branch still has upstream's arm there: for a receiver that is not a Proxy and aCustomValueproperty it callscustomSetter(receiver->realm(), JSValue::encode(receiver), ...). So a receiver that is not the holder (in Bun: the global object of anode:vmcontext) still reaches the native setter with the receiver and the receiver's realm. Upgrade to upstream WebKit 1d4bed41aca8 #992 (comment) has the two ways to resolve it: keep the test for a Proxy and passslot.slotBase()and its realm, or requireslot.slotBase() == receiverfor the arm.main.WeakHandleOwner::finalize()returnsFinalizeResulthere andvoidon Bun'smain.