Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/document fragment #641

Merged
merged 26 commits into from
Sep 24, 2021
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
f2aa5d0
feat: add JSDocumentFragment
answershuto Aug 27, 2021
a812a99
feat: add flog of node.
answershuto Aug 27, 2021
53dc2d8
feat: append children of document fragment when element is DocumentFr…
answershuto Aug 27, 2021
62a76e4
fix: append children.
answershuto Aug 30, 2021
4751df8
feat: insertBefore support documentFragment.
answershuto Aug 30, 2021
6fb734f
test: add documentFragment test.
answershuto Aug 30, 2021
dcbf753
test: new line.
answershuto Aug 30, 2021
d09f8e6
feat: add document.createDocumentFragment.
answershuto Aug 30, 2021
23938f7
test: add test of document.createDocumentFragment.
answershuto Aug 30, 2021
0135a88
test: delete test images.
answershuto Aug 30, 2021
eebd8c7
Merge branch 'main' into feat/DocumentFragment
answershuto Aug 30, 2021
b9b64a8
fix: DocumentFragment don't need create in dart.
answershuto Aug 31, 2021
d1b451a
feat: add DocumentFragmentElement to dart.
answershuto Aug 31, 2021
eec6198
feat: DocumentFragment should be Node.
answershuto Aug 31, 2021
cdb4cd8
chore: deal with lint.
answershuto Aug 31, 2021
cd8263a
chore: delete invalid import.
answershuto Aug 31, 2021
3c0b25c
feat: modify document.createDocumentFragment
answershuto Aug 31, 2021
c93971c
chore: remove document_fragment.
answershuto Aug 31, 2021
2c527ae
feat: doocument fragment instance should be set flag of IsDocumentFra…
answershuto Sep 1, 2021
c78b259
feat: delete invalid initialization.
answershuto Sep 1, 2021
ef418f4
Merge branch 'main' into feat/DocumentFragment
answershuto Sep 1, 2021
57895e4
Merge branch 'main' into feat/DocumentFragment
answershuto Sep 2, 2021
a420815
Merge branch 'main' into feat/DocumentFragment
answershuto Sep 23, 2021
700cf64
Merge branch 'main' into feat/DocumentFragment
answershuto Sep 23, 2021
5884392
chore: delete useless variables.
answershuto Sep 24, 2021
36e991c
refactor: refactor ensureDetached in node.
andycall Sep 24, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions bridge/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,8 @@ if ($ENV{KRAKEN_JS_ENGINE} MATCHES "jsc")
bindings/jsc/DOM/elements/object_element.h
bindings/jsc/DOM/elements/svg_element.cc
bindings/jsc/DOM/elements/svg_element.h
bindings/jsc/DOM/elements/document_fragment.cc
bindings/jsc/DOM/elements/document_fragment.h
bindings/jsc/DOM/elements/script_element.cc
bindings/jsc/DOM/elements/script_element.h
bindings/jsc/KOM/performance.cc
Expand Down
7 changes: 7 additions & 0 deletions bridge/bindings/jsc/DOM/document.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,13 @@ JSValueRef JSDocument::createEvent(JSContextRef ctx, JSObjectRef function, JSObj
}
}

JSValueRef JSDocument::createDocumentFragment(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) {
auto document = static_cast<DocumentInstance *>(JSObjectGetPrivate(thisObject));
std::string strDocumentFragment = "documentFragment";
auto element = JSElement::buildElementInstance(document->context, strDocumentFragment);
return element->object;
}

JSValueRef JSDocument::createElement(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception) {
Expand Down
1 change: 1 addition & 0 deletions bridge/bindings/jsc/DOM/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
#include "bindings/jsc/DOM/elements/input_element.h"
#include "bindings/jsc/DOM/elements/object_element.h"
#include "bindings/jsc/DOM/elements/script_element.h"
#include "bindings/jsc/DOM/elements/document_fragment.h"
#include "bindings/jsc/DOM/events/input_event.h"
#include "bindings/jsc/DOM/events/media_error_event.h"
#include "bindings/jsc/DOM/events/message_event.h"
Expand Down
44 changes: 44 additions & 0 deletions bridge/bindings/jsc/DOM/elements/document_fragment.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
/*
* Copyright (C) 2021 Alibaba Inc. All rights reserved.
* Author: Kraken Team.
*/

#include "document_fragment.h"

namespace kraken::binding::jsc {

void bindDocumentFragment(std::unique_ptr<JSContext> &context) {
auto DocumentFragment = JSDocumentFragment::instance(context.get());
JSC_GLOBAL_SET_PROPERTY(context, "DocumentFragment", DocumentFragment->classObject);
}

std::unordered_map<JSContext *, JSDocumentFragment *> JSDocumentFragment::instanceMap{};

JSDocumentFragment::~JSDocumentFragment() {
instanceMap.erase(context);
}

JSDocumentFragment::JSDocumentFragment(JSContext *context) : JSElement(context) {}
JSObjectRef JSDocumentFragment::instanceConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount,
const JSValueRef *arguments, JSValueRef *exception) {
auto instance = new DocumentFragmentInstance(this);
instance->setNodeFlag(DocumentFragmentInstance::NodeFlag::IsDocumentFragment);
return instance->object;
}

JSDocumentFragment::DocumentFragmentInstance::DocumentFragmentInstance(JSDocumentFragment *jsDocumentFragment)
: NodeInstance(jsDocumentFragment, NodeType::DOCUMENT_FRAGMENT_NODE) {
nativeNode = new NativeNode(new NativeEventTarget(this));
std::string tagName = "documentfragment";
NativeString args_01{};
buildUICommandArgs(tagName, args_01);

foundation::UICommandBuffer::instance(context->getContextId())
->addCommand(eventTargetId, UICommand::createDocumentFragment, args_01, nativeNode);
}

JSDocumentFragment::DocumentFragmentInstance::~DocumentFragmentInstance() {
delete nativeNode;
}

} // namespace kraken::binding::jsc
45 changes: 45 additions & 0 deletions bridge/bindings/jsc/DOM/elements/document_fragment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/*
* Copyright (C) 2021 Alibaba Inc. All rights reserved.
* Author: Kraken Team.
*/

#ifndef KRAKENBRIDGE_DOCUMENT_FRAGMENT_ELEMENT_H
#define KRAKENBRIDGE_DOCUMENT_FRAGMENT_ELEMENT_H

#include "bindings/jsc/DOM/element.h"
#include "bindings/jsc/js_context_internal.h"

namespace kraken::binding::jsc {

void bindDocumentFragment(std::unique_ptr<JSContext> &context);

class JSDocumentFragment : public JSElement {
public:
static std::unordered_map<JSContext *, JSDocumentFragment *> instanceMap;
OBJECT_INSTANCE(JSDocumentFragment)
JSObjectRef instanceConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount,
const JSValueRef *arguments, JSValueRef *exception) override;

class DocumentFragmentInstance : public NodeInstance {
public:

DocumentFragmentInstance() = delete;
~DocumentFragmentInstance();
explicit DocumentFragmentInstance(JSDocumentFragment *JSDocumentFragment);

JSDocumentFragment *nativeDocumentFragment;

private:
JSStringHolder m_data{context, ""};
JSStringHolder m_type{context, ""};
};
protected:
~JSDocumentFragment();
JSDocumentFragment() = delete;
explicit JSDocumentFragment(JSContext *context);
};


} // namespace kraken::binding::jsc

#endif // KRAKENBRIDGE_DOCUMENT_FRAGMENT_ELEMENT_H
17 changes: 15 additions & 2 deletions bridge/bindings/jsc/DOM/node.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

#include "node.h"
#include "document.h"
#include "bindings/jsc/DOM/elements/document_fragment.h"

namespace kraken::binding::jsc {

Expand Down Expand Up @@ -269,7 +270,13 @@ JSValueRef JSNode::appendChild(JSContextRef ctx, JSObjectRef function, JSObjectR
return nullptr;
}

selfInstance->internalAppendChild(nodeInstance);
if (nodeInstance->hasNodeFlag(NodeInstance::NodeFlag::IsDocumentFragment)) {
while (nodeInstance->childNodes.size()) {
selfInstance->internalAppendChild(nodeInstance->childNodes[0]);
}
} else {
selfInstance->internalAppendChild(nodeInstance);
}

return nodeValueRef;
}
Expand Down Expand Up @@ -310,7 +317,13 @@ JSValueRef JSNode::insertBefore(JSContextRef ctx, JSObjectRef function, JSObject
return nullptr;
}

selfInstance->internalInsertBefore(nodeInstance, referenceInstance, exception);
if (nodeInstance->hasNodeFlag(NodeInstance::NodeFlag::IsDocumentFragment)) {
while (nodeInstance->childNodes.size()) {
selfInstance->internalInsertBefore(nodeInstance->childNodes[0], referenceInstance, exception);
}
} else {
selfInstance->internalInsertBefore(nodeInstance, referenceInstance, exception);
}

return nullptr;
}
Expand Down
2 changes: 2 additions & 0 deletions bridge/bridge_jsc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
#include "bindings/jsc/DOM/elements/image_element.h"
#include "bindings/jsc/DOM/elements/input_element.h"
#include "bindings/jsc/DOM/elements/svg_element.h"
#include "bindings/jsc/DOM/elements/document_fragment.h"
#include "bindings/jsc/DOM/event.h"
#include "bindings/jsc/DOM/custom_event.h"
#include "bindings/jsc/DOM/events/gesture_event.h"
Expand Down Expand Up @@ -118,6 +119,7 @@ JSBridge::JSBridge(int32_t contextId, const JSExceptionHandler &handler) : conte
bindImageElement(m_context);
bindInputElement(m_context);
bindSVGElement(m_context);
bindDocumentFragment(m_context);
bindWindow(m_context);
bindPerformance(m_context);
bindCSSStyleDeclaration(m_context);
Expand Down
1 change: 1 addition & 0 deletions bridge/include/kraken_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,7 @@ enum UICommand {
removeProperty,
cloneNode,
removeEvent,
createDocumentFragment,
};

struct KRAKEN_EXPORT UICommandItem {
Expand Down
15 changes: 14 additions & 1 deletion bridge/include/kraken_bridge_jsc.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include <cassert>
#include <functional>
#include <map>
#include <set>
#include <unordered_map>
#include <vector>
#include <forward_list>
Expand Down Expand Up @@ -582,6 +583,15 @@ class JSNode : public JSEventTarget {

class NodeInstance : public EventTargetInstance {
public:
enum class NodeFlag : uint32_t {
IsDocumentFragment = 1 << 0
};

mutable std::set<NodeFlag> m_nodeFlags;
bool hasNodeFlag(NodeFlag flag) const { return m_nodeFlags.size() != 0 && m_nodeFlags.find(flag) != m_nodeFlags.end(); }
void setNodeFlag(NodeFlag flag) const { m_nodeFlags.insert(flag); }
void removeNodeFlag(NodeFlag flag) const { m_nodeFlags.erase(flag); }

NodeInstance() = delete;
NodeInstance(JSNode *node, NodeType nodeType);
NodeInstance(JSNode *node, NodeType nodeType, int64_t targetId);
Expand Down Expand Up @@ -646,6 +656,8 @@ class JSDocument : public JSNode {

static JSValueRef createElement(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount,
const JSValueRef arguments[], JSValueRef *exception);
static JSValueRef createDocumentFragment(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject,
size_t argumentCount, const JSValueRef arguments[], JSValueRef *exception);

static JSValueRef createTextNode(JSContextRef ctx, JSObjectRef function, JSObjectRef thisObject, size_t argumentCount,
const JSValueRef arguments[], JSValueRef *exception);
Expand All @@ -668,6 +680,7 @@ class JSDocument : public JSNode {

JSFunctionHolder m_createEvent{context, prototypeObject, this, "createEvent", createEvent};
JSFunctionHolder m_createElement{context, prototypeObject, this, "createElement", createElement};
JSFunctionHolder m_createDocumentFragment{context, prototypeObject, this, "createDocumentFragment", createDocumentFragment};
JSFunctionHolder m_createTextNode{context, prototypeObject, this, "createTextNode", createTextNode};
JSFunctionHolder m_createComment{context, prototypeObject, this, "createComment", createComment};
JSFunctionHolder m_getElementById{context, prototypeObject, this, "getElementById", getElementById};
Expand Down Expand Up @@ -695,7 +708,7 @@ struct NativeDocument {
class DocumentInstance : public NodeInstance {
public:
DEFINE_OBJECT_PROPERTY(Document, 4, nodeName, all, cookie, documentElement);
DEFINE_PROTOTYPE_OBJECT_PROPERTY(Document, 6, createElement, createTextNode, createComment, getElementById,
DEFINE_PROTOTYPE_OBJECT_PROPERTY(Document, 7, createElement, createDocumentFragment, createTextNode, createComment, getElementById,
getElementsByTagName, createEvent);

static DocumentInstance *instance(JSContext *context);
Expand Down
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
76 changes: 76 additions & 0 deletions integration_tests/specs/dom/elements/documentFragment.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
describe('Tags documentFragment', () => {
it('should work with appendChild', async () => {
const list = document.createElement('div');
document.body.appendChild(list);

const colors = ['red', 'green', 'blue', 'black'];

const fragment = new DocumentFragment();

colors.forEach(color => {
const ele = document.createElement('div');
ele.style.width = '100px';
ele.style.height = '100px';
ele.style.backgroundColor = color;
fragment.appendChild(ele);
});

list.appendChild(fragment);

await snapshot();
});

it('should work with insertBefore', async () => {
const list = document.createElement('div');
document.body.appendChild(list);

const e = document.createElement('div');
e.style.width = '100px';
e.style.height = '100px';
e.style.backgroundColor = 'yellow';
list.appendChild(e);

const colors = ['red', 'green', 'blue', 'black'];

const fragment = new DocumentFragment();

colors.forEach(color => {
const ele = document.createElement('div');
ele.style.width = '100px';
ele.style.height = '100px';
ele.style.backgroundColor = color;
fragment.appendChild(ele);
});

list.insertBefore(fragment, e);

await snapshot();
});

it('should work with createDocumentFragment', async () => {
const list = document.createElement('div');
document.body.appendChild(list);

const e = document.createElement('div');
e.style.width = '100px';
e.style.height = '100px';
e.style.backgroundColor = 'yellow';
list.appendChild(e);

const colors = ['red', 'green', 'blue', 'black'];

const fragment = document.createDocumentFragment();

colors.forEach(color => {
const ele = document.createElement('div');
ele.style.width = '100px';
ele.style.height = '100px';
ele.style.backgroundColor = color;
fragment.appendChild(ele);
});

list.insertBefore(fragment, e);

await snapshot();
});
});
1 change: 1 addition & 0 deletions kraken/lib/dom.dart
Original file line number Diff line number Diff line change
Expand Up @@ -30,3 +30,4 @@ export 'src/dom/elements/input.dart';
export 'src/dom/elements/object.dart';
export 'src/dom/elements/head.dart';
export 'src/dom/elements/html.dart';
export 'src/dom/elements/document_fragment.dart';
4 changes: 4 additions & 0 deletions kraken/lib/src/bridge/to_native.dart
Original file line number Diff line number Diff line change
Expand Up @@ -241,6 +241,7 @@ enum UICommandType {
removeProperty,
cloneNode,
removeEvent,
createDocumentFragment,
}

class UICommandItem extends Struct {
Expand Down Expand Up @@ -454,6 +455,9 @@ void flushUICommand() {
String key = command.args[0];
controller.view.removeProperty(id, key);
break;
case UICommandType.createDocumentFragment:
controller.view.createDocumentFragment(id, nativePtr.cast<NativeNode>());
break;
default:
break;
}
Expand Down
5 changes: 5 additions & 0 deletions kraken/lib/src/dom/element_manager.dart
Original file line number Diff line number Diff line change
Expand Up @@ -170,6 +170,11 @@ class ElementManager implements WidgetsBindingObserver, ElementsBindingObserver
setEventTarget(textNode);
}

void createDocumentFragment(int id, Pointer<NativeNode> nativePtr) {
DocumentFragment documentFragment = DocumentFragment(id, nativePtr, this);
setEventTarget(documentFragment);
}

void createComment(int id, Pointer<NativeCommentNode> nativePtr, String data) {
EventTarget comment = Comment(id, nativePtr, this, data);
setEventTarget(comment);
Expand Down
17 changes: 17 additions & 0 deletions kraken/lib/src/dom/elements/document_fragment.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
/*
* Copyright (C) 2021-present Alibaba Inc. All rights reserved.
* Author: Kraken Team.
*/

import 'package:kraken/dom.dart';
import 'package:flutter/rendering.dart';

const String DOCUMENT_FRAGMENT = 'DOCUMENTFRAGMENT';

class DocumentFragment extends Node {
wssgcg1213 marked this conversation as resolved.
Show resolved Hide resolved
DocumentFragment(int targetId, nativeNodePtr, ElementManager elementManager)
: super(NodeType.COMMENT_NODE, targetId, nativeNodePtr, elementManager, '#documentfragment');

@override
RenderObject? get renderer => null;
}
10 changes: 10 additions & 0 deletions kraken/lib/src/launcher/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,16 @@ class KrakenViewController {
}
}

void createDocumentFragment(int targetId, Pointer<NativeNode> nativePtr) {
if (kProfileMode) {
PerformanceTiming.instance().mark(PERF_CREATE_DOCUMENT_FRAGMENT_START, uniqueId: targetId);
}
_elementManager.createDocumentFragment(targetId, nativePtr);
if (kProfileMode) {
PerformanceTiming.instance().mark(PERF_CREATE_DOCUMENT_FRAGMENT_END, uniqueId: targetId);
}
}

EventTarget? getEventTargetById(int id) {
return _elementManager.getEventTargetByTargetId<EventTarget>(id);
}
Expand Down
2 changes: 2 additions & 0 deletions kraken/lib/src/module/performance_timing.dart
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ final String PERF_FLUSH_UI_COMMAND_START = 'flush_ui_command_start';
final String PERF_FLUSH_UI_COMMAND_END = 'flush_ui_command_end';
final String PERF_CREATE_ELEMENT_START = 'create_element_start';
final String PERF_CREATE_ELEMENT_END = 'create_element_end';
final String PERF_CREATE_DOCUMENT_FRAGMENT_START = 'create_document_fragment_start';
final String PERF_CREATE_DOCUMENT_FRAGMENT_END = 'create_document_fragment_end';
final String PERF_CREATE_TEXT_NODE_START = 'create_text_node_start';
final String PERF_CREATE_TEXT_NODE_END = 'create_text_node_end';
final String PERF_CREATE_COMMENT_START = 'create_comment_start';
Expand Down