diff options
Diffstat (limited to 'chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc')
-rw-r--r-- | chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc | 205 |
1 files changed, 162 insertions, 43 deletions
diff --git a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc index 3ac1c1fbcb5..b662f819135 100644 --- a/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc +++ b/chromium/third_party/blink/renderer/core/layout/ng/custom/css_layout_definition.cc @@ -13,6 +13,8 @@ #include "third_party/blink/renderer/bindings/core/v8/v8_binding_for_core.h" #include "third_party/blink/renderer/bindings/core/v8/v8_fragment_result_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_function.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_intrinsic_sizes_callback.h" +#include "third_party/blink/renderer/bindings/core/v8/v8_intrinsic_sizes_result_options.h" #include "third_party/blink/renderer/bindings/core/v8/v8_layout_callback.h" #include "third_party/blink/renderer/bindings/core/v8/v8_no_argument_constructor.h" #include "third_party/blink/renderer/core/css/cssom/prepopulated_computed_style_property_map.h" @@ -23,20 +25,41 @@ #include "third_party/blink/renderer/core/layout/ng/custom/custom_layout_edges.h" #include "third_party/blink/renderer/core/layout/ng/custom/custom_layout_fragment.h" #include "third_party/blink/renderer/core/layout/ng/custom/custom_layout_scope.h" -#include "third_party/blink/renderer/core/layout/ng/custom/fragment_result_options.h" #include "third_party/blink/renderer/core/layout/ng/ng_block_node.h" #include "third_party/blink/renderer/core/layout/ng/ng_layout_input_node.h" #include "third_party/blink/renderer/platform/bindings/microtask.h" #include "third_party/blink/renderer/platform/bindings/script_state.h" #include "third_party/blink/renderer/platform/bindings/v8_binding_macros.h" #include "third_party/blink/renderer/platform/bindings/v8_object_constructor.h" +#include "third_party/blink/renderer/platform/heap/heap.h" namespace blink { +namespace { + +void GatherChildren(const NGBlockNode& node, + CustomLayoutScope* custom_layout_scope, + HeapVector<Member<CustomLayoutChild>>* children) { + // TODO(ikilpatrick): Determine if knowing the size of the array ahead of + // time improves performance in any noticeable way. + for (NGLayoutInputNode child = node.FirstChild(); child; + child = child.NextSibling()) { + if (child.IsOutOfFlowPositioned()) + continue; + + CustomLayoutChild* layout_child = child.GetCustomLayoutChild(); + layout_child->SetCustomLayoutToken(custom_layout_scope->Token()); + DCHECK(layout_child); + children->push_back(layout_child); + } +} + +} // anonymous namespace + CSSLayoutDefinition::CSSLayoutDefinition( ScriptState* script_state, V8NoArgumentConstructor* constructor, - V8Function* intrinsic_sizes, + V8IntrinsicSizesCallback* intrinsic_sizes, V8LayoutCallback* layout, const Vector<CSSPropertyID>& native_invalidation_properties, const Vector<AtomicString>& custom_invalidation_properties, @@ -44,7 +67,7 @@ CSSLayoutDefinition::CSSLayoutDefinition( const Vector<AtomicString>& child_custom_invalidation_properties) : script_state_(script_state), constructor_(constructor), - unused_intrinsic_sizes_(intrinsic_sizes), + intrinsic_sizes_(intrinsic_sizes), layout_(layout), native_invalidation_properties_(native_invalidation_properties), custom_invalidation_properties_(custom_invalidation_properties), @@ -66,8 +89,9 @@ bool CSSLayoutDefinition::Instance::Layout( const NGBlockNode& node, const LogicalSize& border_box_size, const NGBoxStrut& border_scrollbar_padding, + const LayoutUnit child_percentage_resolution_block_size_for_min_max, CustomLayoutScope* custom_layout_scope, - FragmentResultOptions* fragment_result_options, + FragmentResultOptions*& fragment_result_options, scoped_refptr<SerializedScriptValue>* fragment_result_data) { ScriptState* script_state = definition_->GetScriptState(); v8::Isolate* isolate = script_state->GetIsolate(); @@ -77,19 +101,8 @@ bool CSSLayoutDefinition::Instance::Layout( ScriptState::Scope scope(script_state); - // TODO(ikilpatrick): Determine if knowing the size of the array ahead of - // time improves performance in any noticeable way. HeapVector<Member<CustomLayoutChild>> children; - for (NGLayoutInputNode child = node.FirstChild(); child; - child = child.NextSibling()) { - if (child.IsOutOfFlowPositioned()) - continue; - - CustomLayoutChild* layout_child = child.GetCustomLayoutChild(); - layout_child->SetCustomLayoutToken(custom_layout_scope->Token()); - DCHECK(layout_child); - children.push_back(layout_child); - } + GatherChildren(node, custom_layout_scope, &children); CustomLayoutEdges* edges = MakeGarbageCollected<CustomLayoutEdges>(border_scrollbar_padding); @@ -121,18 +134,20 @@ bool CSSLayoutDefinition::Instance::Layout( v8::Local<v8::Value> v8_return_value = return_value.V8Value(); if (v8_return_value.IsEmpty() || !v8_return_value->IsPromise()) { - execution_context->AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript, - mojom::ConsoleMessageLevel::kInfo, - "The layout function must be async or return a " - "promise, falling back to block layout.")); + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kInfo, + "The layout function must be async or return a " + "promise, falling back to block layout.")); return false; } // Run the work queue until exhaustion. while (!custom_layout_scope->Queue()->IsEmpty()) { - for (auto& task : *custom_layout_scope->Queue()) - task.Run(space, node.Style()); + for (auto& task : *custom_layout_scope->Queue()) { + task.Run(space, node.Style(), + child_percentage_resolution_block_size_for_min_max); + } custom_layout_scope->Queue()->clear(); { v8::MicrotasksScope microtasks_scope(isolate, microtask_queue, @@ -149,27 +164,28 @@ bool CSSLayoutDefinition::Instance::Layout( v8::Local<v8::Promise>::Cast(v8_return_value); if (v8_result_promise->State() != v8::Promise::kFulfilled) { - execution_context->AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript, - mojom::ConsoleMessageLevel::kInfo, - "The layout function promise must resolve, " - "falling back to block layout.")); + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kInfo, + "The layout function promise must resolve, " + "falling back to block layout.")); return false; } v8::Local<v8::Value> inner_value = v8_result_promise->Result(); // Attempt to convert the result. - V8FragmentResultOptions::ToImpl(isolate, inner_value, fragment_result_options, - exception_state); + fragment_result_options = + NativeValueTraits<FragmentResultOptions>::NativeValue( + isolate, inner_value, exception_state); if (exception_state.HadException()) { V8ScriptRunner::ReportException(isolate, exception_state.GetException()); exception_state.ClearException(); - execution_context->AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript, - mojom::ConsoleMessageLevel::kInfo, - "Unable to parse the layout function " - "result, falling back to block layout.")); + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kInfo, + "Unable to parse the layout function " + "result, falling back to block layout.")); return false; } @@ -188,11 +204,114 @@ bool CSSLayoutDefinition::Instance::Layout( if (exception_state.HadException()) { V8ScriptRunner::ReportException(isolate, exception_state.GetException()); exception_state.ClearException(); - execution_context->AddConsoleMessage( - ConsoleMessage::Create(mojom::ConsoleMessageSource::kJavaScript, - mojom::ConsoleMessageLevel::kInfo, - "Unable to serialize the data provided in the " - "result, falling back to block layout.")); + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kInfo, + "Unable to serialize the data provided in the " + "result, falling back to block layout.")); + return false; + } + + return true; +} + +bool CSSLayoutDefinition::Instance::IntrinsicSizes( + const NGConstraintSpace& space, + const Document& document, + const NGBlockNode& node, + const LogicalSize& border_box_size, + const NGBoxStrut& border_scrollbar_padding, + const LayoutUnit child_percentage_resolution_block_size_for_min_max, + CustomLayoutScope* custom_layout_scope, + IntrinsicSizesResultOptions*& intrinsic_sizes_result_options) { + ScriptState* script_state = definition_->GetScriptState(); + v8::Isolate* isolate = script_state->GetIsolate(); + + if (!script_state->ContextIsValid()) + return false; + + ScriptState::Scope scope(script_state); + + HeapVector<Member<CustomLayoutChild>> children; + GatherChildren(node, custom_layout_scope, &children); + + CustomLayoutEdges* edges = + MakeGarbageCollected<CustomLayoutEdges>(border_scrollbar_padding); + + // TODO(ikilpatrick): Instead of creating a new style_map each time here, + // store on LayoutCustom, and update when the style changes. + StylePropertyMapReadOnly* style_map = + MakeGarbageCollected<PrepopulatedComputedStylePropertyMap>( + document, node.Style(), definition_->native_invalidation_properties_, + definition_->custom_invalidation_properties_); + + ScriptValue return_value; + if (!definition_->intrinsic_sizes_ + ->Invoke(instance_.NewLocal(isolate), children, edges, style_map) + .To(&return_value)) + return false; + + ExecutionContext* execution_context = ExecutionContext::From(script_state); + v8::MicrotaskQueue* microtask_queue = ToMicrotaskQueue(execution_context); + DCHECK(microtask_queue); + + ExceptionState exception_state(isolate, ExceptionState::kExecutionContext, + "CSSLayoutAPI", "IntrinsicSizes"); + + v8::Local<v8::Value> v8_return_value = return_value.V8Value(); + if (v8_return_value.IsEmpty() || !v8_return_value->IsPromise()) { + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kInfo, + "The intrinsicSizes function must be async or return a " + "promise, falling back to block layout.")); + return false; + } + + // Run the work queue until exhaustion. + while (!custom_layout_scope->Queue()->IsEmpty()) { + for (auto& task : *custom_layout_scope->Queue()) { + task.Run(space, node.Style(), + child_percentage_resolution_block_size_for_min_max); + } + custom_layout_scope->Queue()->clear(); + { + v8::MicrotasksScope microtasks_scope(isolate, microtask_queue, + v8::MicrotasksScope::kRunMicrotasks); + } + } + + if (exception_state.HadException()) { + ReportException(&exception_state); + return false; + } + + v8::Local<v8::Promise> v8_result_promise = + v8::Local<v8::Promise>::Cast(v8_return_value); + + if (v8_result_promise->State() != v8::Promise::kFulfilled) { + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kInfo, + "The intrinsicSizes function promise must resolve, " + "falling back to block layout.")); + return false; + } + v8::Local<v8::Value> inner_value = v8_result_promise->Result(); + + // Attempt to convert the result. + intrinsic_sizes_result_options = + NativeValueTraits<IntrinsicSizesResultOptions>::NativeValue( + isolate, inner_value, exception_state); + + if (exception_state.HadException()) { + V8ScriptRunner::ReportException(isolate, exception_state.GetException()); + exception_state.ClearException(); + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( + mojom::ConsoleMessageSource::kJavaScript, + mojom::ConsoleMessageLevel::kInfo, + "Unable to parse the intrinsicSizes function " + "result, falling back to block layout.")); return false; } @@ -209,7 +328,7 @@ void CSSLayoutDefinition::Instance::ReportException( // again (as the callbacks are invoked directly by the UA). V8ScriptRunner::ReportException(isolate, exception_state->GetException()); exception_state->ClearException(); - execution_context->AddConsoleMessage(ConsoleMessage::Create( + execution_context->AddConsoleMessage(MakeGarbageCollected<ConsoleMessage>( mojom::ConsoleMessageSource::kJavaScript, mojom::ConsoleMessageLevel::kInfo, "The layout function failed, falling back to block layout.")); @@ -234,14 +353,14 @@ CSSLayoutDefinition::Instance* CSSLayoutDefinition::CreateInstance() { return MakeGarbageCollected<Instance>(this, instance.V8Value()); } -void CSSLayoutDefinition::Instance::Trace(blink::Visitor* visitor) { +void CSSLayoutDefinition::Instance::Trace(Visitor* visitor) { visitor->Trace(definition_); visitor->Trace(instance_); } void CSSLayoutDefinition::Trace(Visitor* visitor) { visitor->Trace(constructor_); - visitor->Trace(unused_intrinsic_sizes_); + visitor->Trace(intrinsic_sizes_); visitor->Trace(layout_); visitor->Trace(script_state_); } |