Skip to content

Commit

Permalink
refactor: refactor initialize and refactor timer.
Browse files Browse the repository at this point in the history
  • Loading branch information
andycall committed Feb 7, 2022
1 parent 9fd04e1 commit 63f27a7
Show file tree
Hide file tree
Showing 31 changed files with 521 additions and 243 deletions.
11 changes: 8 additions & 3 deletions bridge/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,8 @@ if ($ENV{KRAKEN_JS_ENGINE} MATCHES "quickjs")
# Binding files
bindings/qjs/binding_initializer.cc
bindings/qjs/binding_initializer.h
bindings/qjs/member_installer.cc
bindings/qjs/member_installer.h
bindings/qjs/garbage_collected.h
bindings/qjs/wrapper_type_info.h
bindings/qjs/heap_hashmap.h
Expand All @@ -203,9 +205,12 @@ if ($ENV{KRAKEN_JS_ENGINE} MATCHES "quickjs")
bindings/qjs/script_value.h
bindings/qjs/exception_state.cc
bindings/qjs/exception_state.h

bindings/qjs/timer.cc
bindings/qjs/timer.h
bindings/qjs/visitor.cc
bindings/qjs/visitor.h
bindings/qjs/rejected_promises.h
bindings/qjs/rejected_promises.cc
bindings/qjs/qjs_window.cc
bindings/qjs/qjs_window.h

# Core sources
core/executing_context.cc
Expand Down
6 changes: 5 additions & 1 deletion bridge/bindings/qjs/binding_initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@

#include "binding_initializer.h"

#include "qjs_window.h"

//#include "bindings/qjs/bom/blob.h"
//#include "bindings/qjs/bom/console.h"
//#include "bindings/qjs/bom/location.h"
Expand Down Expand Up @@ -41,6 +43,8 @@

namespace kraken {

void initBinding() {}
void installBindings(JSContext* ctx) {
QJSWindow::installGlobalFunctions(ctx);
}

} // namespace kraken
39 changes: 3 additions & 36 deletions bridge/bindings/qjs/binding_initializer.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,44 +6,11 @@
#ifndef KRAKENBRIDGE_BINDING_INITIALIZER_H
#define KRAKENBRIDGE_BINDING_INITIALIZER_H

namespace kraken {
#include <quickjs/quickjs.h>

void initBinding();
namespace kraken {

// bindConsole(m_context);
// bindTimer(m_context);
// bindScreen(m_context);
// bindModuleManager(m_context);
// bindEventTarget(m_context);
// bindBlob(m_context);
// bindLocation(m_context);
// bindWindow(m_context);
// bindEvent(m_context);
// bindCustomEvent(m_context);
// bindNode(m_context);
// bindDocumentFragment(m_context);
// bindTextNode(m_context);
// bindCommentNode(m_context);
// bindElement(m_context);
// bindAnchorElement(m_context);
// bindCanvasElement(m_context);
// bindImageElement(m_context);
// bindInputElement(m_context);
// bindObjectElement(m_context);
// bindScriptElement(m_context);
// bindTemplateElement(m_context);
// bindCSSStyleDeclaration(m_context);
// bindCloseEvent(m_context);
// bindGestureEvent(m_context);
// bindInputEvent(m_context);
// bindIntersectionChangeEvent(m_context);
// bindMediaErrorEvent(m_context);
// bindMouseEvent(m_context);
// bindMessageEvent(m_context);
// bindPopStateEvent(m_context);
// bindTouchEvent(m_context);
// bindDocument(m_context);
// bindPerformance(m_context);
void installBindings(JSContext* ctx);

} // namespace kraken

Expand Down
32 changes: 32 additions & 0 deletions bridge/bindings/qjs/exception_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,35 @@
*/

#include "exception_state.h"

namespace kraken {

void ExceptionState::throwException(JSContext* ctx, ErrorType type, const char* message) {
switch(type) {
case ErrorType::TypeError:
m_exception = JS_ThrowTypeError(ctx, "%s", message);
break;
case InternalError :
m_exception = JS_ThrowInternalError(ctx, "%s", message);
break;
case RangeError:
m_exception = JS_ThrowRangeError(ctx, "%s", message);
break;
case ReferenceError:
m_exception = JS_ThrowReferenceError(ctx, "%s", message);
break;
case SyntaxError:
m_exception = JS_ThrowSyntaxError(ctx, "%s", message);
break;
}
}

bool ExceptionState::hasException() {
return !JS_IsNull(m_exception);
}

JSValue ExceptionState::toQuickJS() {
return m_exception;
}

}
16 changes: 15 additions & 1 deletion bridge/bindings/qjs/exception_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,26 @@
#ifndef KRAKENBRIDGE_EXCEPTION_STATE_H
#define KRAKENBRIDGE_EXCEPTION_STATE_H

#include <quickjs/quickjs.h>

namespace kraken {

// ExceptionState is a scope-like class and provides a way to throw an exception.
enum ErrorType {
TypeError,
InternalError,
RangeError,
ReferenceError,
SyntaxError
};

// ExceptionState is a scope-like class and provides a way to store an exception.
class ExceptionState {
public:
void throwException(JSContext* ctx, ErrorType type, const char* message);
bool hasException();
JSValue toQuickJS();
private:
JSValue m_exception{JS_NULL};
};

} // namespace kraken
Expand Down
9 changes: 6 additions & 3 deletions bridge/bindings/qjs/garbage_collected.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

#include "foundation/macros.h"
#include "qjs_patch.h"
#include "visitor.h"

namespace kraken {

Expand Down Expand Up @@ -55,7 +56,7 @@ class GarbageCollected {
* This Trace method must be override by objects inheriting from
* GarbageCollected.
*/
virtual void trace(JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func) const = 0;
virtual void trace(Visitor* visitor) const = 0;

/**
* Called before underline JavaScript object been collected by GC.
Expand All @@ -81,6 +82,7 @@ class GarbageCollected {
JSContext* m_ctx{nullptr};
JSRuntime* m_runtime{nullptr};
GarbageCollected(){};
GarbageCollected(JSContext* ctx): m_runtime(JS_GetRuntime(ctx)), m_ctx(ctx) {};
friend class MakeGarbageCollectedTrait<T>;
};

Expand All @@ -102,7 +104,7 @@ P* GarbageCollected<T>::initialize(JSContext* ctx, JSClassID* classId, JSClassEx
JSRuntime* runtime = JS_GetRuntime(ctx);

/// When classId is 0, it means this class are not initialized. We should create a JSClassDef to describe the behavior of this class and associate with classID.
/// ClassId should be a static value to make sure JSClassDef when this class are created at the first class.
/// ClassId should be a static toQuickJS to make sure JSClassDef when this class are created at the first class.
if (*classId == 0 || !JS_HasClassId(runtime, *classId)) {
/// Allocate a new unique classID from QuickJS.
JS_NewClassID(classId);
Expand All @@ -116,7 +118,8 @@ P* GarbageCollected<T>::initialize(JSContext* ctx, JSClassID* classId, JSClassEx
/// which member of their class should be collected by GC.
def.gc_mark = [](JSRuntime* rt, JSValueConst val, JS_MarkFunc* mark_func) {
auto* object = static_cast<P*>(JS_GetOpaque(val, JSValueGetClassId(val)));
object->trace(rt, val, mark_func);
Visitor visitor{rt, mark_func};
object->trace(&visitor);
};

/// Define custom behavior when call getProperty, setProperty on object.
Expand Down
32 changes: 32 additions & 0 deletions bridge/bindings/qjs/member_installer.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
/*
* Copyright (C) 2019 Alibaba Inc. All rights reserved.
* Author: Kraken Team.
*/

#include "member_installer.h"

namespace kraken {

int combinePropFlags(JSPropFlag a, JSPropFlag b) {
return a | b;
}
int combinePropFlags(JSPropFlag a, JSPropFlag b, JSPropFlag c) {
return a | b | c;
}

void MemberInstaller::installAttributes(JSContext* ctx, JSValue root, std::initializer_list<MemberInstaller::AttributeConfig> config) {
for (auto& c : config) {
JS_DefinePropertyValueStr(ctx, root, c.name, JS_DupValue(ctx, c.value), c.flag);
}
}

int compilePropFlags();

void MemberInstaller::installFunctions(JSContext* ctx, JSValue root, std::initializer_list<FunctionConfig> config) {
for (auto& c : config) {
JSValue function = JS_NewCFunction(ctx, c.function, c.name, c.length);
JS_DefinePropertyValueStr(ctx, root, c.name, function, c.flag);
}
}

} // namespace kraken
50 changes: 50 additions & 0 deletions bridge/bindings/qjs/member_installer.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
/*
* Copyright (C) 2019 Alibaba Inc. All rights reserved.
* Author: Kraken Team.
*/

#ifndef KRAKENBRIDGE_MEMBER_INSTALLER_H
#define KRAKENBRIDGE_MEMBER_INSTALLER_H

#include <quickjs/quickjs.h>
#include <initializer_list>

namespace kraken {

// Flags for object properties.
enum JSPropFlag {
normal = JS_PROP_NORMAL,
writable = JS_PROP_WRITABLE,
enumerable = JS_PROP_ENUMERABLE,
configurable = JS_PROP_CONFIGURABLE
};

// Combine multiple prop flags.
int combinePropFlags(JSPropFlag a, JSPropFlag b);
int combinePropFlags(JSPropFlag a, JSPropFlag b, JSPropFlag c);

// A set of utility functions to define attributes members as ES properties.
class MemberInstaller {
public:
struct AttributeConfig {
AttributeConfig& operator=(const AttributeConfig&) = delete;
const char* name;
JSValue value;
int flag; // Flags for object properties.
};

struct FunctionConfig {
FunctionConfig& operator=(const FunctionConfig&) = delete;
const char* name;
JSCFunction* function;
size_t length;
int flag; // Flags for object properties.
};

static void installAttributes(JSContext* ctx, JSValue root, std::initializer_list<AttributeConfig>);
static void installFunctions(JSContext* ctx, JSValue root, std::initializer_list<FunctionConfig>);
};

}

#endif // KRAKENBRIDGE_MEMBER_INSTALLER_H
38 changes: 38 additions & 0 deletions bridge/bindings/qjs/qjs_function.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,41 @@
*/

#include "qjs_function.h"
#include <algorithm>

namespace kraken {

bool QJSFunction::isFunction(JSContext* ctx) {
return JS_IsFunction(ctx, m_function);
}

ScriptValue QJSFunction::invoke(JSContext* ctx, int32_t argc, ScriptValue* arguments) {
// 'm_function' might be destroyed when calling itself (if it frees the handler), so must take extra care.
JS_DupValue(ctx, m_function);

JSValue argv[std::max(1, argc)];

for(int i = 0; i < argc; i ++) {
argv[0 + i] = arguments[i].toQuickJS();
}

JSValue returnValue = JS_Call(ctx, m_function, JS_UNDEFINED, argc, argv);

// Free the previous duplicated function.
JS_FreeValue(m_ctx, m_function);

return ScriptValue(ctx, returnValue);
}

const char* QJSFunction::getHumanReadableName() const {
return "QJSFunction";
}

void QJSFunction::trace(Visitor* visitor) const {
visitor->trace(m_function);
}

void QJSFunction::dispose() const {
JS_FreeValueRT(m_runtime, m_function);
}
}
14 changes: 8 additions & 6 deletions bridge/bindings/qjs/qjs_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,22 +7,24 @@
#define KRAKENBRIDGE_QJS_FUNCTION_H

#include "garbage_collected.h"
#include "script_value.h"

namespace kraken {

// https://webidl.spec.whatwg.org/#dfn-callback-interface
class QJSFunction : public GarbageCollected<QJSFunction> {
public:
static QJSFunction* create(JSContext* ctx, JSValue function) { return makeGarbageCollected<QJSFunction>(ctx, function); }
explicit QJSFunction(JSContext* ctx, JSValue function) : m_function(JS_DupValue(ctx, function)), GarbageCollected<QJSFunction>(ctx) {};

explicit QJSFunction(JSContext* ctx, JSValue function) : m_function(JS_DupValue(ctx, function)){};
bool isFunction(JSContext* ctx);

const char* getHumanReadableName() const override;

[[nodiscard]]
// Performs "invoke".
// https://webidl.spec.whatwg.org/#invoke-a-callback-function
ScriptValue invoke(JSContext* ctx, int32_t argc, ScriptValue* arguments);

void
trace(JSRuntime* rt, JSValue val, JS_MarkFunc* mark_func) const override;
const char* getHumanReadableName() const override;
void trace(Visitor* visitor) const override;
void dispose() const override;

private:
Expand Down
Loading

0 comments on commit 63f27a7

Please sign in to comment.