diff --git a/bridge/core/dom/intersection_observer.cc b/bridge/core/dom/intersection_observer.cc index 67270b2274..bb1e845793 100644 --- a/bridge/core/dom/intersection_observer.cc +++ b/bridge/core/dom/intersection_observer.cc @@ -9,17 +9,22 @@ #include #include -#include "core/dom/element.h" -#include #include "bindings/qjs/converter_impl.h" +#include "core/dom/element.h" #include "core/dom/intersection_observer_entry.h" #include "core/dom/node.h" #include "core/executing_context.h" -#include "qjs_intersection_observer_init.h" #include "foundation/logging.h" +#include "foundation/native_value_converter.h" +#include "qjs_intersection_observer_init.h" namespace webf { +struct NativeIntersectionObserverEntry : public DartReadable { + int8_t is_intersecting; + NativeBindingObject* target; +}; + IntersectionObserver* IntersectionObserver::Create(ExecutingContext* context, const std::shared_ptr& function, ExceptionState& exception_state) { @@ -105,28 +110,33 @@ NativeValue IntersectionObserver::HandleCallFromDartSide(const AtomicString& met int32_t argc, const NativeValue* argv, Dart_Handle dart_object) { - if (!GetExecutingContext() || !GetExecutingContext()->IsContextValid()) { + if (!GetExecutingContext() || !GetExecutingContext()->IsContextValid()) { WEBF_LOG(ERROR) << "[IntersectionObserver]: HandleCallFromDartSide Context Valid" << std::endl; return Native_NewNull(); } + MemberMutationScope scope{GetExecutingContext()}; WEBF_LOG(DEBUG) << "[IntersectionObserver]: HandleCallFromDartSide NativeValueConverter" << std::endl; - NativeValue native_entry_list = argv[0]; - std::vector entries = - NativeValueConverter>>::FromNativeValue( - ctx(), native_entry_list); + NativeIntersectionObserverEntry* native_entry = + NativeValueConverter>::FromNativeValue(argv[0]); + size_t length = NativeValueConverter::FromNativeValue(argv[1]); - if (!entries.empty()) { + if (length > 0) { assert(function_ != nullptr); - WEBF_LOG(DEBUG) << "[IntersectionObserver]: HandleCallFromDartSide To JSValue" << std::endl; - JSValue v = Converter>::ToValue(ctx(), entries); - ScriptValue arguments[] = {ScriptValue(ctx(), v), ToValue()}; - - JS_FreeValue(ctx(), v); + JSValue js_array = JS_NewArray(ctx()); + for (int i = 0; i < length; i++) { + auto* entry = MakeGarbageCollected( + GetExecutingContext(), native_entry[i].is_intersecting, + DynamicTo(BindingObject::From(native_entry[i].target))); + JS_SetPropertyUint32(ctx(), js_array, i, entry->ToQuickJS()); + } + ScriptValue arguments[] = {ScriptValue(ctx(), js_array), ToValue()}; WEBF_LOG(DEBUG) << "[IntersectionObserver]: HandleCallFromDartSide function_ Invoke" << std::endl; function_->Invoke(ctx(), ToValue(), 2, arguments); + + JS_FreeValue(ctx(), js_array); } else { WEBF_LOG(ERROR) << "[IntersectionObserver]: HandleCallFromDartSide entries is empty"; } diff --git a/webf/lib/src/dom/intersection_observer.dart b/webf/lib/src/dom/intersection_observer.dart index 2b18a172f2..c5f31f3443 100644 --- a/webf/lib/src/dom/intersection_observer.dart +++ b/webf/lib/src/dom/intersection_observer.dart @@ -19,6 +19,7 @@ class _IntersectionObserverDeliverContext { // Pointer method; Pointer allocatedNativeArguments; + //Pointer rawNativeEntries; WebFController controller; EvaluateOpItem? profileOp; @@ -33,7 +34,8 @@ class _IntersectionObserverDeliverContext { ); } -void _handleDeliverResult(_IntersectionObserverDeliverContext context, Pointer returnValue) { +void _handleDeliverResult(Object handle, Pointer returnValue) { + _IntersectionObserverDeliverContext context = handle as _IntersectionObserverDeliverContext; Pointer dispatchResult = fromNativeValue(context.controller.view, returnValue).cast(); @@ -99,35 +101,17 @@ class IntersectionObserver extends DynamicBindingObject { _entries.add(entry); } - List takeRecords() { + List takeRecords() { List entries = _entries.map((entry) => entry.copy()).toList(); _entries.clear(); - return toNativeEntries(entries); - } - - List toNativeEntries(List entries) { - if (entries.isEmpty) { - return []; - } - - return List.generate(entries.length, (i) { - return NativeIntersectionObserverEntry( - BindingContext( - entries[i].element.ownerView, - entries[i].element.ownerView.contextId, - allocateNewBindingObject(), - ), - entries[i].isIntersecting, - entries[i].element, - ); - }); + return entries; } Future deliver(WebFController controller) async { if (pointer == null) return; debugPrint('Dom.IntersectionObserver.deliver pointer:$pointer'); - List nativeEntries = takeRecords(); - if (nativeEntries.isNotEmpty) { + List entries = takeRecords(); + if (entries.isNotEmpty) { Completer completer = Completer(); EvaluateOpItem? currentProfileOp; @@ -139,16 +123,26 @@ class IntersectionObserver extends DynamicBindingObject { // Call methods implements at C++ side. DartInvokeBindingMethodsFromDart? f = pointer!.ref.invokeBindingMethodFromDart.asFunction(); - // Pointer method = malloc.allocate(sizeOf()); - // toNativeValue(method, 'deliver'); - - List dispatchEntryArguments = [nativeEntries]; - Stopwatch? stopwatch; if (enableWebFCommandLog) { stopwatch = Stopwatch()..start(); } + // Allocate an chunk of memory for an list of NativeIntersectionObserverEntry + Pointer head = + malloc.allocate(sizeOf() * entries.length); + + // Write the native memory from dart objects. + for(int i = 0; i < entries.length; i ++) { + (head + i).ref.isIntersecting = entries[i].isIntersecting ? 1 : 0; + (head + i).ref.target = entries[i].element.pointer!; + } + + List dispatchEntryArguments = [ + head, + entries.length + ]; + Pointer allocatedNativeArguments = makeNativeValueArguments(bindingObject, dispatchEntryArguments); _IntersectionObserverDeliverContext context = _IntersectionObserverDeliverContext( @@ -167,6 +161,7 @@ class IntersectionObserver extends DynamicBindingObject { // Pointer> result_callback); f(pointer!, currentProfileOp?.hashCode ?? 0, nullptr, dispatchEntryArguments.length, allocatedNativeArguments, context, resultCallback); + malloc.free(head); }); return completer.future; diff --git a/webf/lib/src/dom/intersection_observer_entry.dart b/webf/lib/src/dom/intersection_observer_entry.dart index dc208cb4f9..ce4291cfcf 100644 --- a/webf/lib/src/dom/intersection_observer_entry.dart +++ b/webf/lib/src/dom/intersection_observer_entry.dart @@ -3,7 +3,8 @@ * Copyright (C) 2022-present The WebF authors. All rights reserved. */ -import 'package:webf/foundation.dart'; +import 'dart:ffi'; +import 'package:webf/bridge.dart'; import 'element.dart'; class DartIntersectionObserverEntry { @@ -24,26 +25,9 @@ class DartIntersectionObserverEntry { } } -class NativeIntersectionObserverEntry extends DynamicBindingObject { - //final DOMHighResTimeStamp time; - //final DOMRectReadOnly? rootBounds; - //final DOMRectReadOnly boundingClientRect; - //final DOMRectReadOnly intersectionRect; - final bool isIntersecting; - - //final bool isVisible; - //final double intersectionRatio; - final Element target; - - NativeIntersectionObserverEntry(BindingContext context, this.isIntersecting, this.target) : super(context); +class NativeIntersectionObserverEntry extends Struct { + @Int8() + external int isIntersecting; - @override - void initializeMethods(Map methods) { - // TODO: implement initializeMethods - } - - @override - void initializeProperties(Map properties) { - // TODO: implement initializeProperties - } + external Pointer target; }