Skip to content

Commit

Permalink
feat: timer global functions
Browse files Browse the repository at this point in the history
  • Loading branch information
LeuisKen authored and andycall committed Nov 10, 2024
1 parent d03f421 commit 137098e
Show file tree
Hide file tree
Showing 18 changed files with 497 additions and 161 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
42 changes: 1 addition & 41 deletions bridge/core/api/event_target.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,50 +20,10 @@
#include "core/html/html_image_element.h"
#include "html_element_type_helper.h"
#include "plugin_api/add_event_listener_options.h"
#include "plugin_api/webf_event_listener.h"

namespace webf {

class WebFPublicPluginEventListener : public EventListener {
public:
WebFPublicPluginEventListener(WebFEventListenerContext* callback_context,
SharedExceptionState* shared_exception_state)
: callback_context_(callback_context), shared_exception_state_(shared_exception_state) {}

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

static const std::shared_ptr<WebFPublicPluginEventListener> Create(WebFEventListenerContext* WebF_event_listener,
SharedExceptionState* shared_exception_state) {
return std::make_shared<WebFPublicPluginEventListener>(WebF_event_listener, shared_exception_state);
};

[[nodiscard]] bool IsPublicPluginEventHandler() const override { return true; }

void Invoke(ExecutingContext* context, Event* event, ExceptionState& exception_state) override {
WebFValueStatus* status_block = event->KeepAlive();
callback_context_->callback(callback_context_, event, event->eventPublicMethods(), status_block,
shared_exception_state_);
}

[[nodiscard]] bool Matches(const EventListener& other) const override {
const auto* other_listener = DynamicTo<WebFPublicPluginEventListener>(other);
return other_listener && other_listener->callback_context_ &&
other_listener->callback_context_->callback == callback_context_->callback;
}

void Trace(GCVisitor* visitor) const override {}

WebFEventListenerContext* callback_context_;
SharedExceptionState* shared_exception_state_;
};

template <>
struct DowncastTraits<WebFPublicPluginEventListener> {
static bool AllowFrom(const EventListener& event_listener) { return event_listener.IsPublicPluginEventHandler(); }
};

void EventTargetPublicMethods::AddEventListener(EventTarget* event_target,
const char* event_name_str,
WebFEventListenerContext* callback_context,
Expand Down
31 changes: 31 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 @@ -31,4 +32,34 @@ void ExecutingContextWebFMethods::FinishRecordingUIOperations(webf::ExecutingCon
context->uiCommandBuffer()->AddCommand(UICommand::kFinishRecordingCommand, nullptr, nullptr, nullptr, false);
}

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);
}

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

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

void ExecutingContextWebFMethods::ClearTimeout(ExecutingContext* context, int32_t timeout_id,
SharedExceptionState* shared_exception_state) {
WindowOrWorkerGlobalScope::clearTimeout(context, timeout_id, shared_exception_state->exception_state);
}

void ExecutingContextWebFMethods::ClearInterval(ExecutingContext* context, int32_t interval_id,
SharedExceptionState* shared_exception_state) {
WindowOrWorkerGlobalScope::clearInterval(context, interval_id, 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;
typedef struct WebFNativeFunctionContext 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_
13 changes: 0 additions & 13 deletions bridge/include/plugin_api/event_target.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,6 @@ class Event;
typedef struct EventPublicMethods EventPublicMethods;
typedef struct WebFEventListenerContext WebFEventListenerContext;

using WebFImplEventCallback = void (*)(WebFEventListenerContext* callback_context,
Event* event,
const EventPublicMethods* event_methods,
WebFValueStatus* status,
SharedExceptionState* shared_exception_state);
using FreePtrFn = void (*)(WebFEventListenerContext* callback_context);

enum class EventTargetType {
kEventTarget = 0,
kNode = 1,
Expand All @@ -42,12 +35,6 @@ enum class EventTargetType {
kComment = 13,
};

struct WebFEventListenerContext : public RustReadable {
WebFImplEventCallback callback;
FreePtrFn free_ptr;
void* ptr;
};

using PublicEventTargetAddEventListener = void (*)(EventTarget* event_target,
const char*,
WebFEventListenerContext* callback_context,
Expand Down
Loading

0 comments on commit 137098e

Please sign in to comment.