Skip to content

Commit

Permalink
feat: timer global functions
Browse files Browse the repository at this point in the history
  • Loading branch information
LeuisKen committed Nov 8, 2024
1 parent 8457894 commit 213ea44
Show file tree
Hide file tree
Showing 13 changed files with 235 additions and 39 deletions.
11 changes: 10 additions & 1 deletion bridge/bindings/qjs/qjs_function.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
#ifndef BRIDGE_QJS_FUNCTION_H
#define BRIDGE_QJS_FUNCTION_H

#include "foundation/casting.h"
#include "foundation/function.h"
#include "script_value.h"

namespace webf {
Expand All @@ -17,7 +19,7 @@ using QJSFunctionCallback = ScriptValue (*)(JSContext* ctx,

// https://webidl.spec.whatwg.org/#dfn-callback-interface
// QJSFunction memory are auto managed by std::shared_ptr.
class QJSFunction {
class QJSFunction : public Function {
public:
static std::shared_ptr<QJSFunction> Create(JSContext* ctx, JSValue function) {
return std::make_shared<QJSFunction>(ctx, function);
Expand Down Expand Up @@ -46,6 +48,8 @@ class QJSFunction {

bool IsFunction(JSContext* ctx);

bool IsQJSFunction() const override { return true; }

JSValue ToQuickJS() { return JS_DupValue(ctx_, function_); };
JSValue ToQuickJSUnsafe() { return function_; }

Expand All @@ -66,6 +70,11 @@ class QJSFunction {
JSValue this_val_{JS_NULL};
};

template <>
struct DowncastTraits<QJSFunction> {
static bool AllowFrom(const Function& function) { return function.IsQJSFunction(); }
};

} // namespace webf

#endif // BRIDGE_QJS_FUNCTION_H
11 changes: 11 additions & 0 deletions bridge/core/api/executing_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "core/dom/document.h"
#include "core/executing_context.h"
#include "core/frame/window.h"
#include "core/frame/window_or_worker_global_scope.h"

namespace webf {

Expand All @@ -27,4 +28,14 @@ WebFValue<SharedExceptionState, ExceptionStatePublicMethods> ExecutingContextWeb
ExceptionState::publicMethodPointer(), nullptr);
}

int32_t ExecutingContextWebFMethods::SetTimeout(ExecutingContext* context,
WebFNativeFunctionContext* callback_context,
int32_t timeout,
SharedExceptionState* shared_exception_state) {
auto callback_impl = WebFNativeFunction::Create(callback_context, shared_exception_state);

return WindowOrWorkerGlobalScope::setTimeout(context, callback_impl, timeout,
shared_exception_state->exception_state);
}

} // namespace webf
18 changes: 11 additions & 7 deletions bridge/core/frame/dom_timer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -16,25 +16,29 @@
namespace webf {

std::shared_ptr<DOMTimer> DOMTimer::create(ExecutingContext* context,
const std::shared_ptr<QJSFunction>& callback,
const std::shared_ptr<Function>& callback,
TimerKind timer_kind) {
return std::make_shared<DOMTimer>(context, callback, timer_kind);
}

DOMTimer::DOMTimer(ExecutingContext* context, std::shared_ptr<QJSFunction> callback, TimerKind timer_kind)
DOMTimer::DOMTimer(ExecutingContext* context, std::shared_ptr<Function> callback, TimerKind timer_kind)
: context_(context), callback_(std::move(callback)), status_(TimerStatus::kPending), kind_(timer_kind) {}

void DOMTimer::Fire() {
if (status_ == TimerStatus::kTerminated)
return;

if (!callback_->IsFunction(context_->ctx()))
return;
if (auto* callback = DynamicTo<QJSFunction>(callback_.get())) {
if (!callback->IsFunction(context_->ctx()))
return;

ScriptValue returnValue = callback_->Invoke(context_->ctx(), ScriptValue::Empty(context_->ctx()), 0, nullptr);
ScriptValue returnValue = callback->Invoke(context_->ctx(), ScriptValue::Empty(context_->ctx()), 0, nullptr);

if (returnValue.IsException()) {
context_->HandleException(&returnValue);
if (returnValue.IsException()) {
context_->HandleException(&returnValue);
}
} else if (auto* callback = DynamicTo<WebFNativeFunction>(callback_.get())) {
callback->Invoke(context_, 0, nullptr);
}
}

Expand Down
6 changes: 3 additions & 3 deletions bridge/core/frame/dom_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,9 @@ class DOMTimer {
enum TimerStatus { kPending, kExecuting, kFinished, kCanceled, kTerminated };

static std::shared_ptr<DOMTimer> create(ExecutingContext* context,
const std::shared_ptr<QJSFunction>& callback,
const std::shared_ptr<Function>& callback,
TimerKind timer_kind);
DOMTimer(ExecutingContext* context, std::shared_ptr<QJSFunction> callback, TimerKind timer_kind);
DOMTimer(ExecutingContext* context, std::shared_ptr<Function> callback, TimerKind timer_kind);

// Trigger timer callback.
void Fire();
Expand All @@ -42,7 +42,7 @@ class DOMTimer {
ExecutingContext* context_{nullptr};
int32_t timer_id_{-1};
TimerStatus status_;
std::shared_ptr<QJSFunction> callback_;
std::shared_ptr<Function> callback_;
};

} // namespace webf
Expand Down
8 changes: 4 additions & 4 deletions bridge/core/frame/window_or_worker_global_scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -105,13 +105,13 @@ static void handlePersistentCallbackWrapper(void* ptr, double contextId, char* e
}

int WindowOrWorkerGlobalScope::setTimeout(ExecutingContext* context,
const std::shared_ptr<QJSFunction>& handler,
const std::shared_ptr<Function>& handler,
ExceptionState& exception) {
return setTimeout(context, handler, 0.0, exception);
}

int WindowOrWorkerGlobalScope::setTimeout(ExecutingContext* context,
const std::shared_ptr<QJSFunction>& handler,
const std::shared_ptr<Function>& handler,
int32_t timeout,
ExceptionState& exception) {
if (handler == nullptr) {
Expand All @@ -133,13 +133,13 @@ int WindowOrWorkerGlobalScope::setTimeout(ExecutingContext* context,
}

int WindowOrWorkerGlobalScope::setInterval(ExecutingContext* context,
std::shared_ptr<QJSFunction> handler,
std::shared_ptr<Function> handler,
ExceptionState& exception) {
return setInterval(context, handler, 0.0, exception);
}

int WindowOrWorkerGlobalScope::setInterval(ExecutingContext* context,
const std::shared_ptr<QJSFunction>& handler,
const std::shared_ptr<Function>& handler,
int32_t timeout,
ExceptionState& exception) {
if (handler == nullptr) {
Expand Down
11 changes: 5 additions & 6 deletions bridge/core/frame/window_or_worker_global_scope.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,23 +8,22 @@
#include "bindings/qjs/exception_state.h"
#include "bindings/qjs/qjs_function.h"
#include "core/executing_context.h"
#include "foundation/function.h"

namespace webf {

class WindowOrWorkerGlobalScope {
public:
static int setTimeout(ExecutingContext* context,
const std::shared_ptr<QJSFunction>& handler,
const std::shared_ptr<Function>& handler,
int32_t timeout,
ExceptionState& exception);
static int setTimeout(ExecutingContext* context,
const std::shared_ptr<QJSFunction>& handler,
ExceptionState& exception);
static int setTimeout(ExecutingContext* context, const std::shared_ptr<Function>& handler, ExceptionState& exception);
static int setInterval(ExecutingContext* context,
const std::shared_ptr<QJSFunction>& handler,
const std::shared_ptr<Function>& handler,
int32_t timeout,
ExceptionState& exception);
static int setInterval(ExecutingContext* context, std::shared_ptr<QJSFunction> handler, ExceptionState& exception);
static int setInterval(ExecutingContext* context, std::shared_ptr<Function> handler, ExceptionState& exception);
static void clearTimeout(ExecutingContext* context, int32_t timerId, ExceptionState& exception);
static void clearInterval(ExecutingContext* context, int32_t timerId, ExceptionState& exception);
static void __gc__(ExecutingContext* context, ExceptionState& exception);
Expand Down
63 changes: 63 additions & 0 deletions bridge/core/native/native_function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
/*
* Copyright (C) 2022-present The WebF authors. All rights reserved.
*/

#ifndef WEBF_CORE_NATIVE_NATIVE_FUNCTION_H_
#define WEBF_CORE_NATIVE_NATIVE_FUNCTION_H_

#include "foundation/casting.h"
#include "foundation/function.h"
#include "foundation/native_value.h"
#include "plugin_api/rust_readable.h"

namespace webf {

class SharedExceptionState;
struct WebFNativeFunctionContext;

using WebFNativeFunctionCallback = void (*)(WebFNativeFunctionContext* callback_context,
int32_t argc,
NativeValue* argv,
SharedExceptionState* shared_exception_state);
using WebFNativeFunctionFreePtrFn = void (*)(WebFNativeFunctionContext* callback_context);

struct WebFNativeFunctionContext : public RustReadable {
WebFNativeFunctionCallback callback;
WebFNativeFunctionFreePtrFn free_ptr;
void* ptr;
};

class WebFNativeFunction : public Function {
public:
WebFNativeFunction(WebFNativeFunctionContext* callback_context, SharedExceptionState* shared_exception_state)
: callback_context_(callback_context), shared_exception_state_(shared_exception_state) {}

static const std::shared_ptr<WebFNativeFunction> Create(WebFNativeFunctionContext* callback_context,
SharedExceptionState* shared_exception_state) {
return std::make_shared<WebFNativeFunction>(callback_context, shared_exception_state);
}

~WebFNativeFunction() {
callback_context_->free_ptr(callback_context_);
delete callback_context_;
}

bool IsWebFNativeFunction() const override { return true; }

void Invoke(ExecutingContext* context, int32_t argc, NativeValue* argv) {
callback_context_->callback(callback_context_, argc, argv, shared_exception_state_);
}

private:
WebFNativeFunctionContext* callback_context_;
SharedExceptionState* shared_exception_state_;
};

template <>
struct DowncastTraits<WebFNativeFunction> {
static bool AllowFrom(const Function& function) { return function.IsWebFNativeFunction(); }
};

} // namespace webf

#endif // WEBF_CORE_NATIVE_NATIVE_FUNCTION_H_
19 changes: 19 additions & 0 deletions bridge/foundation/function.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/*
* Copyright (C) 2019-2022 The Kraken authors. All rights reserved.
* Copyright (C) 2022-present The WebF authors. All rights reserved.
*/

#ifndef BRIDGE_FOUNDATION_FUNCTION_H_
#define BRIDGE_FOUNDATION_FUNCTION_H_

namespace webf {

class Function {
public:
virtual bool IsQJSFunction() const { return false; }
virtual bool IsWebFNativeFunction() const { return false; }
};

} // namespace webf

#endif // BRIDGE_FOUNDATION_FUNCTION_H_
16 changes: 13 additions & 3 deletions bridge/include/plugin_api/executing_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
#ifndef WEBF_CORE_RUST_API_EXECUTING_CONTEXT_H_
#define WEBF_CORE_RUST_API_EXECUTING_CONTEXT_H_

#include "core/native/native_function.h"
#include "document.h"
#include "exception_state.h"
#include "window.h"
Expand All @@ -18,18 +19,27 @@ class Window;
using PublicContextGetDocument = WebFValue<Document, DocumentPublicMethods> (*)(ExecutingContext*);
using PublicContextGetWindow = WebFValue<Window, WindowPublicMethods> (*)(ExecutingContext*);
using PublicContextGetExceptionState = WebFValue<SharedExceptionState, ExceptionStatePublicMethods> (*)();
using PublicContextSetTimeout = int32_t (*)(ExecutingContext*,
WebFNativeFunctionContext*,
int32_t,
SharedExceptionState*);

// Memory aligned and readable from WebF side.
// Only C type member can be included in this class, any C++ type and classes can is not allowed to use here.
struct ExecutingContextWebFMethods {
static WebFValue<Document, DocumentPublicMethods> document(ExecutingContext* context);
static WebFValue<Window, WindowPublicMethods> window(ExecutingContext* context);
static WebFValue<SharedExceptionState, ExceptionStatePublicMethods> CreateExceptionState();
static int32_t SetTimeout(ExecutingContext* context,
WebFNativeFunctionContext* callback_context,
int32_t timeout,
SharedExceptionState* shared_exception_state);

double version{1.0};
PublicContextGetDocument rust_context_get_document_{document};
PublicContextGetWindow rust_context_get_window_{window};
PublicContextGetExceptionState rust_context_get_exception_state_{CreateExceptionState};
PublicContextGetDocument context_get_document{document};
PublicContextGetWindow context_get_window{window};
PublicContextGetExceptionState context_get_exception_state{CreateExceptionState};
PublicContextSetTimeout context_set_timeout{SetTimeout};
};

} // namespace webf
Expand Down
6 changes: 3 additions & 3 deletions bridge/rusty_webf_sys/src/event_target.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use crate::node::{Node, NodeRustMethods};
use crate::window::{Window, WindowRustMethods};

#[repr(C)]
struct EventCallbackContext {
pub struct EventCallbackContext {
pub callback: extern "C" fn(event_callback_context: *const OpaquePtr,
event: *const OpaquePtr,
event_method_pointer: *const EventRustMethods,
Expand All @@ -26,7 +26,7 @@ struct EventCallbackContext {
pub ptr: *const EventCallbackContextData,
}

struct EventCallbackContextData {
pub struct EventCallbackContextData {
executing_context_ptr: *const OpaquePtr,
executing_context_method_pointer: *const ExecutingContextRustMethods,
func: EventListenerCallback,
Expand All @@ -42,7 +42,7 @@ pub trait RustMethods {}


#[repr(C)]
enum EventTargetType {
pub enum EventTargetType {
EventTarget = 0,
Node = 1,
ContainerNode = 2,
Expand Down
Loading

0 comments on commit 213ea44

Please sign in to comment.