Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: timer global functions #683

Merged
merged 1 commit into from
Nov 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading