Skip to content

Commit

Permalink
refactor: refactor node, element and document.
Browse files Browse the repository at this point in the history
  • Loading branch information
andycall committed Jan 11, 2022
1 parent d6f00d7 commit 3449e36
Show file tree
Hide file tree
Showing 16 changed files with 750 additions and 699 deletions.
12 changes: 10 additions & 2 deletions bridge/bindings/qjs/bom/window.cc
Original file line number Diff line number Diff line change
Expand Up @@ -162,10 +162,18 @@ IMPL_FUNCTION(Window, cancelAnimationFrame)(JSContext* ctx, JSValue this_val, in
}

Window* Window::create(JSContext* ctx) {
return makeGarbageCollected<Window>()->initialize<Window>(ctx, &classId, nullptr);
auto* context = static_cast<ExecutionContext*>(JS_GetContextOpaque(ctx));
JSValue prototype = context->contextData()->prototypeForType(&windowTypeInfo);

auto* window = makeGarbageCollected<Window>()->initialize<Window>(ctx, &classId, nullptr);

// Let window inherit Window prototype methods.
JS_SetPrototype(ctx, window->toQuickJS(), prototype);

return window;
}

DocumentInstance* Window::document() {
Document* Window::document() {
return context()->document();
}

Expand Down
9 changes: 1 addition & 8 deletions bridge/bindings/qjs/bom/window.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,22 +45,15 @@ class Window : public EventTarget {
void trace(JSRuntime *rt, JSValue val, JS_MarkFunc *mark_func) const override;

private:
DocumentInstance* document();
Document* document();

Location* m_location{nullptr};
JSValue onerror{JS_NULL};
friend ExecutionContext;
};

auto windowCreator = [](JSContext* ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst* argv, int flags) -> JSValue {

auto* type = static_cast<const WrapperTypeInfo*>(JS_GetOpaque(func_obj, JSValueGetClassId(func_obj)));
auto* window = Window::create(ctx);
auto* context = static_cast<ExecutionContext*>(JS_GetContextOpaque(ctx));
JSValue prototype = context->contextData()->prototypeForType(type);

// Let eventTarget instance inherit EventTarget prototype methods.
JS_SetPrototype(ctx, window->toQuickJS(), prototype);
return window->toQuickJS();
};

Expand Down
263 changes: 134 additions & 129 deletions bridge/bindings/qjs/dom/document.cc

Large diffs are not rendered by default.

121 changes: 56 additions & 65 deletions bridge/bindings/qjs/dom/document.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,37 @@ namespace kraken::binding::qjs {

void bindDocument(std::unique_ptr<ExecutionContext>& context);

using TraverseHandler = std::function<bool(NodeInstance*)>;
using TraverseHandler = std::function<bool(Node*)>;

void traverseNode(NodeInstance* node, TraverseHandler handler);
void traverseNode(Node* node, TraverseHandler handler);

class Document : public Node {
public:
static JSClassID kDocumentClassID;

Document() = delete;
Document(ExecutionContext* context);

static JSClassID classId();
class DocumentCookie {
public:
DocumentCookie() = default;

JSValue instanceConstructor(JSContext* ctx, JSValue func_obj, JSValue this_val, int argc, JSValue* argv) override;
std::string getCookie();
void setCookie(std::string& str);

OBJECT_INSTANCE(Document);
private:
std::unordered_map<std::string, std::string> cookiePairs;
};

static JSValue createEvent(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
static JSValue createElement(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
static JSValue createTextNode(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
static JSValue createDocumentFragment(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
static JSValue createComment(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
static JSValue getElementById(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
static JSValue getElementsByTagName(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);
static JSValue getElementsByClassName(JSContext* ctx, JSValueConst this_val, int argc, JSValueConst* argv);

JSValue getElementConstructor(ExecutionContext* context, const std::string& tagName);
bool isCustomElement(const std::string& tagName);
class Document : public Node {
public:
static JSClassID classId;
Document* create(JSContext* ctx);
explicit Document();

DEFINE_FUNCTION(createEvent);
DEFINE_FUNCTION(createElement);
DEFINE_FUNCTION(createTextNode);
DEFINE_FUNCTION(createDocumentFragment);
DEFINE_FUNCTION(createComment);
DEFINE_FUNCTION(getElementById);
DEFINE_FUNCTION(getElementsByTagName);
DEFINE_FUNCTION(getElementsByClassName);

private:
DEFINE_PROTOTYPE_READONLY_PROPERTY(nodeName);
DEFINE_PROTOTYPE_READONLY_PROPERTY(all);
DEFINE_PROTOTYPE_READONLY_PROPERTY(documentElement);
Expand All @@ -54,58 +55,48 @@ class Document : public Node {
DEFINE_PROTOTYPE_PROPERTY(cookie);
DEFINE_PROTOTYPE_PROPERTY(body);

DEFINE_PROTOTYPE_FUNCTION(createEvent, 1);
DEFINE_PROTOTYPE_FUNCTION(createElement, 1);
DEFINE_PROTOTYPE_FUNCTION(createDocumentFragment, 0);
DEFINE_PROTOTYPE_FUNCTION(createTextNode, 1);
DEFINE_PROTOTYPE_FUNCTION(createComment, 1);
DEFINE_PROTOTYPE_FUNCTION(getElementById, 1);
DEFINE_PROTOTYPE_FUNCTION(getElementsByTagName, 1);
DEFINE_PROTOTYPE_FUNCTION(getElementsByClassName, 1);
JSValue getElementConstructor(ExecutionContext* context, const std::string& tagName);
bool isCustomElement(const std::string& tagName);

void defineElement(const std::string& tagName, Element* constructor);
int32_t requestAnimationFrame(FrameCallback* frameCallback);
void cancelAnimationFrame(uint32_t callbackId);
void trace(JSRuntime* rt, JSValue val, JS_MarkFunc* mark_func) const override;
void dispose() const override;

private:

void removeElementById(JSAtom id, Element* element);
void addElementById(JSAtom id, Element* element);
Element* getDocumentElement();
std::unordered_map<JSAtom, std::vector<Element*>> m_elementMapById;
Element* m_documentElement{nullptr};
std::unique_ptr<DocumentCookie> m_cookie;

ScriptAnimationController* m_scriptAnimationController;
// DEFINE_PROTOTYPE_FUNCTION(createEvent, 1);
// DEFINE_PROTOTYPE_FUNCTION(createElement, 1);
// DEFINE_PROTOTYPE_FUNCTION(createDocumentFragment, 0);
// DEFINE_PROTOTYPE_FUNCTION(createTextNode, 1);
// DEFINE_PROTOTYPE_FUNCTION(createComment, 1);
// DEFINE_PROTOTYPE_FUNCTION(getElementById, 1);
// DEFINE_PROTOTYPE_FUNCTION(getElementsByTagName, 1);
// DEFINE_PROTOTYPE_FUNCTION(getElementsByClassName, 1);

friend DocumentInstance;
void defineElement(const std::string& tagName, Element* constructor);

bool event_registered{false};
bool document_registered{false};
std::unordered_map<std::string, Element*> elementConstructorMap;
};

class DocumentCookie {
public:
DocumentCookie() = default;

std::string getCookie();
void setCookie(std::string& str);

private:
std::unordered_map<std::string, std::string> cookiePairs;
auto documentCreator = [](JSContext* ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst* argv, int flags) -> JSValue {
return JS_ThrowTypeError(ctx, "Illegal constructor");
};

class DocumentInstance : public NodeInstance {
public:
DocumentInstance() = delete;
explicit DocumentInstance(Document* document);
~DocumentInstance();

int32_t requestAnimationFrame(FrameCallback* frameCallback);
void cancelAnimationFrame(uint32_t callbackId);
void trace(JSRuntime* rt, JSValue val, JS_MarkFunc* mark_func) override;

private:
void removeElementById(JSAtom id, ElementInstance* element);
void addElementById(JSAtom id, ElementInstance* element);
ElementInstance* getDocumentElement();
std::unordered_map<JSAtom, std::vector<ElementInstance*>> m_elementMapById;
ElementInstance* m_documentElement{nullptr};
std::unique_ptr<DocumentCookie> m_cookie;

ScriptAnimationController* m_scriptAnimationController;

friend Document;
friend ElementInstance;
friend ExecutionContext;
const WrapperTypeInfo documentTypeInfo = {
"Document",
&nodeTypeInfo,
documentCreator
};

} // namespace kraken::binding::qjs
Expand Down
31 changes: 15 additions & 16 deletions bridge/bindings/qjs/dom/document_fragment.cc
Original file line number Diff line number Diff line change
Expand Up @@ -10,29 +10,28 @@
namespace kraken::binding::qjs {

void bindDocumentFragment(std::unique_ptr<ExecutionContext>& context) {
auto* constructor = DocumentFragment::instance(context.get());
context->defineGlobalProperty("DocumentFragment", constructor->jsObject);
JSValue classObject = context->contextData()->constructorForType(&documentFragmentInfo);
context->defineGlobalProperty("DocumentFragment", classObject);
}

std::once_flag kDocumentFragmentFlag;
JSValue DocumentFragment::constructor(ExecutionContext* context) {
return context->contextData()->constructorForType(&documentFragmentInfo);
}

JSClassID DocumentFragment::kDocumentFragmentID{0};
DocumentFragment * DocumentFragment::create(JSContext* ctx) {
auto* context = static_cast<ExecutionContext*>(JS_GetContextOpaque(ctx));
JSValue prototype = context->contextData()->prototypeForType(&documentFragmentInfo);
auto* documentFragment = makeGarbageCollected<DocumentFragment>()->initialize<DocumentFragment>(ctx, &classId);

DocumentFragment::DocumentFragment(ExecutionContext* context) : Node(context) {
std::call_once(kDocumentFragmentFlag, []() { JS_NewClassID(&kDocumentFragmentID); });
JS_SetPrototype(m_ctx, m_prototypeObject, Node::instance(m_context)->prototype());
}
// Let documentFragment instance inherit Document prototype methods.
JS_SetPrototype(ctx, documentFragment->toQuickJS(), prototype);

JSClassID DocumentFragment::classId() {
return kDocumentFragmentID;
return documentFragment;
}

JSValue DocumentFragment::instanceConstructor(JSContext* ctx, JSValue func_obj, JSValue this_val, int argc, JSValue* argv) {
return (new DocumentFragmentInstance(this))->jsObject;
DocumentFragment::DocumentFragment() {
setNodeFlag(DocumentFragment::NodeFlag::IsDocumentFragment);
context()->uiCommandBuffer()->addCommand(eventTargetId(), UICommand::createDocumentFragment, nativeEventTarget);
}

DocumentFragmentInstance::DocumentFragmentInstance(DocumentFragment* fragment) : NodeInstance(fragment, NodeType::DOCUMENT_FRAGMENT_NODE, DocumentFragment::classId(), "DocumentFragment") {
setNodeFlag(DocumentFragmentInstance::NodeFlag::IsDocumentFragment);
m_context->uiCommandBuffer()->addCommand(m_eventTargetId, UICommand::createDocumentFragment, nativeEventTarget);
}
} // namespace kraken::binding::qjs
28 changes: 16 additions & 12 deletions bridge/bindings/qjs/dom/document_fragment.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,25 @@ void bindDocumentFragment(std::unique_ptr<ExecutionContext>& context);

class DocumentFragment : public Node {
public:
static JSClassID kDocumentFragmentID;
static JSClassID classId();

DocumentFragment() = delete;
explicit DocumentFragment(ExecutionContext* context);

JSValue instanceConstructor(JSContext* ctx, JSValue func_obj, JSValue this_val, int argc, JSValue* argv) override;
static JSClassID classId;
// Return the constructor class object of DocumentFragment.
static JSValue constructor(ExecutionContext* context);
DocumentFragment* create(JSContext* ctx);
DocumentFragment();

private:
friend Node;
};

OBJECT_INSTANCE(DocumentFragment);
auto documentFragmentCreator = [](JSContext* ctx, JSValueConst func_obj, JSValueConst this_val, int argc, JSValueConst* argv, int flags) -> JSValue {
auto* eventTarget = EventTarget::create(ctx);
return eventTarget->toQuickJS();
};

class DocumentFragmentInstance : public NodeInstance {
public:
DocumentFragmentInstance() = delete;
DocumentFragmentInstance(DocumentFragment* fragment);
const WrapperTypeInfo documentFragmentInfo = {
"DocumentFragment",
&nodeTypeInfo,
documentFragmentCreator
};

} // namespace kraken::binding::qjs
Expand Down

0 comments on commit 3449e36

Please sign in to comment.