Skip to content

Commit

Permalink
Merge pull request #641 from openkraken/feat/DocumentFragment
Browse files Browse the repository at this point in the history
Feat/document fragment
  • Loading branch information
answershuto committed Sep 24, 2021
2 parents 28a5c77 + 36e991c commit af43462
Show file tree
Hide file tree
Showing 19 changed files with 311 additions and 53 deletions.
2 changes: 2 additions & 0 deletions bridge/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,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
6 changes: 6 additions & 0 deletions bridge/bindings/jsc/DOM/document.cc
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,12 @@ 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));
auto documentFragment = new JSDocumentFragment::DocumentFragmentInstance(JSDocumentFragment::instance(document->context));
return documentFragment->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/close_event.h"
#include "bindings/jsc/DOM/events/gesture_event.h"
#include "bindings/jsc/DOM/events/input_event.h"
Expand Down
41 changes: 41 additions & 0 deletions bridge/bindings/jsc/DOM/elements/document_fragment.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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) : JSNode(context) {}
JSObjectRef JSDocumentFragment::instanceConstructor(JSContextRef ctx, JSObjectRef constructor, size_t argumentCount,
const JSValueRef *arguments, JSValueRef *exception) {
auto instance = new DocumentFragmentInstance(this);
return instance->object;
}

JSDocumentFragment::DocumentFragmentInstance::DocumentFragmentInstance(JSDocumentFragment *jsDocumentFragment)
: NodeInstance(jsDocumentFragment, NodeType::DOCUMENT_FRAGMENT_NODE) {
setNodeFlag(DocumentFragmentInstance::NodeFlag::IsDocumentFragment);
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() {}

} // namespace kraken::binding::jsc
41 changes: 41 additions & 0 deletions bridge/bindings/jsc/DOM/elements/document_fragment.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
/*
* 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 JSNode {
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;
};
protected:
~JSDocumentFragment();
JSDocumentFragment() = delete;
explicit JSDocumentFragment(JSContext *context);
};


} // namespace kraken::binding::jsc

#endif // KRAKENBRIDGE_DOCUMENT_FRAGMENT_ELEMENT_H
39 changes: 33 additions & 6 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 @@ -190,6 +191,7 @@ void JSNode::traverseCloneNode(JSContextRef ctx, NodeInstance *element, NodeInst
JSValueRef newElementRef = copyNodeValue(ctx, static_cast<NodeInstance *>(iter));
JSObjectRef newElementObjectRef = JSValueToObject(ctx, newElementRef, nullptr);
auto newNodeInstance = static_cast<NodeInstance *>(JSObjectGetPrivate(newElementObjectRef));
parentElement->ensureDetached(newNodeInstance);
parentElement->internalAppendChild(newNodeInstance);
// element node needs recursive child nodes.
if (iter->nodeType == NodeType::ELEMENT_NODE) {
Expand Down Expand Up @@ -269,7 +271,21 @@ JSValueRef JSNode::appendChild(JSContextRef ctx, JSObjectRef function, JSObjectR
return nullptr;
}

selfInstance->internalAppendChild(nodeInstance);
if (nodeInstance->hasNodeFlag(NodeInstance::NodeFlag::IsDocumentFragment)) {
size_t len = nodeInstance->childNodes.size();
for (int i = 0; i < len; i ++) {
selfInstance->internalAppendChild(nodeInstance->childNodes[i]);
}

// Clear fragment childNodes reference.
for (int i = 0; i < len; i ++) {
nodeInstance->childNodes[i]->unrefer();
}
nodeInstance->childNodes.clear();
} else {
selfInstance->ensureDetached(nodeInstance);
selfInstance->internalAppendChild(nodeInstance);
}

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

selfInstance->internalInsertBefore(nodeInstance, referenceInstance, exception);
if (nodeInstance->hasNodeFlag(NodeInstance::NodeFlag::IsDocumentFragment)) {
size_t len = nodeInstance->childNodes.size();
for (int i = 0; i < len; i ++) {
selfInstance->internalInsertBefore(nodeInstance->childNodes[i], referenceInstance, exception);
}

// Clear fragment childNodes reference.
for (int i = 0; i < len; i ++) {
nodeInstance->childNodes[i]->unrefer();
}
nodeInstance->childNodes.clear();
} else {
selfInstance->ensureDetached(nodeInstance);
selfInstance->internalInsertBefore(nodeInstance, referenceInstance, exception);
}

return nullptr;
}
Expand Down Expand Up @@ -360,6 +390,7 @@ JSValueRef JSNode::replaceChild(JSContextRef ctx, JSObjectRef function, JSObject
return nullptr;
}

selfInstance->ensureDetached(newChildInstance);
selfInstance->internalReplaceChild(newChildInstance, oldChildInstance, exception);

return nullptr;
Expand All @@ -376,8 +407,6 @@ void NodeInstance::internalInsertBefore(NodeInstance *node, NodeInstance *refere
exception);
return;
}

ensureDetached(node);
auto parent = referenceNode->parentNode;
if (parent != nullptr) {
auto &&parentChildNodes = parent->childNodes;
Expand Down Expand Up @@ -452,7 +481,6 @@ JSValueRef JSNode::removeChild(JSContextRef ctx, JSObjectRef function, JSObjectR
}

void NodeInstance::internalAppendChild(NodeInstance *node) {
ensureDetached(node);
childNodes.emplace_back(node);
node->parentNode = this;
node->refer();
Expand Down Expand Up @@ -493,7 +521,6 @@ NodeInstance *NodeInstance::internalRemoveChild(NodeInstance *node, JSValueRef *

NodeInstance *NodeInstance::internalReplaceChild(NodeInstance *newChild, NodeInstance *oldChild,
JSValueRef *exception) {
ensureDetached(newChild);
assert_m(newChild->parentNode == nullptr, "ReplaceChild Error: newChild was not detached.");
oldChild->parentNode = nullptr;
oldChild->unrefer();
Expand Down
2 changes: 2 additions & 0 deletions bridge/bridge_jsc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,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/event_target.h"
#include "bindings/jsc/DOM/events/close_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

0 comments on commit af43462

Please sign in to comment.