diff --git a/.github/workflows/code_linter.yml b/.github/workflows/code_linter.yml index 78624cbc20..b7b06c3b4d 100644 --- a/.github/workflows/code_linter.yml +++ b/.github/workflows/code_linter.yml @@ -8,7 +8,7 @@ on: jobs: cppcheck: - runs-on: macos-12 + runs-on: macos-14 name: Cppcheck steps: - uses: actions/checkout@v3 @@ -50,11 +50,9 @@ jobs: extensions: 'h,cc,c' clangFormatVersion: 12 inplace: True - - uses: EndBug/add-and-commit@v4 + - uses: EndBug/add-and-commit@v9 with: - author_name: openwebf-bot - author_email: openwebf@openwebf.com - message: 'Committing clang-format changes' + default_author: github_actions env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/bridge/core/api/executing_context.cc b/bridge/core/api/executing_context.cc index c189ca8607..4e28e7ad86 100644 --- a/bridge/core/api/executing_context.cc +++ b/bridge/core/api/executing_context.cc @@ -7,8 +7,11 @@ #include "core/api/exception_state.h" #include "core/dom/document.h" #include "core/executing_context.h" +#include "core/frame/legacy/location.h" +#include "core/frame/module_manager.h" #include "core/frame/window.h" #include "core/frame/window_or_worker_global_scope.h" +#include "foundation/native_value_converter.h" namespace webf { @@ -32,6 +35,71 @@ void ExecutingContextWebFMethods::FinishRecordingUIOperations(webf::ExecutingCon context->uiCommandBuffer()->AddCommand(UICommand::kFinishRecordingCommand, nullptr, nullptr, nullptr, false); } +NativeValue ExecutingContextWebFMethods::WebFInvokeModule(ExecutingContext* context, + const char* module_name, + const char* method, + SharedExceptionState* shared_exception_state) { + AtomicString module_name_atomic = AtomicString(context->ctx(), module_name); + AtomicString method_atomic = webf::AtomicString(context->ctx(), method); + + ScriptValue result = ModuleManager::__webf_invoke_module__(context, module_name_atomic, method_atomic, + shared_exception_state->exception_state); + NativeValue return_result = result.ToNative(context->ctx(), shared_exception_state->exception_state); + + if (shared_exception_state->exception_state.HasException()) { + return Native_NewNull(); + } + + return return_result; +} + +NativeValue ExecutingContextWebFMethods::WebFInvokeModuleWithParams(ExecutingContext* context, + const char* module_name, + const char* method, + NativeValue* params, + SharedExceptionState* shared_exception_state) { + AtomicString module_name_atomic = AtomicString(context->ctx(), module_name); + AtomicString method_atomic = webf::AtomicString(context->ctx(), method); + + const NativeValue* result = ModuleManager::__webf_invoke_module__(context, module_name_atomic, method_atomic, *params, + nullptr, shared_exception_state->exception_state); + + if (shared_exception_state->exception_state.HasException() || result == nullptr) { + return Native_NewNull(); + } + + NativeValue return_result = *result; + return return_result; +} + +NativeValue ExecutingContextWebFMethods::WebFInvokeModuleWithParamsAndCallback( + ExecutingContext* context, + const char* module_name, + const char* method, + NativeValue* params, + WebFNativeFunctionContext* callback_context, + SharedExceptionState* shared_exception_state) { + AtomicString module_name_atomic = AtomicString(context->ctx(), module_name); + AtomicString method_atomic = webf::AtomicString(context->ctx(), method); + + auto callback_impl = WebFNativeFunction::Create(callback_context, shared_exception_state); + + const NativeValue* result = ModuleManager::__webf_invoke_module__( + context, module_name_atomic, method_atomic, *params, callback_impl, shared_exception_state->exception_state); + + if (shared_exception_state->exception_state.HasException()) { + return Native_NewNull(); + } + + NativeValue return_result = *result; + return return_result; +} + +void ExecutingContextWebFMethods::WebFLocationReload(ExecutingContext* context, + SharedExceptionState* shared_exception_state) { + Location::__webf_location_reload__(context, shared_exception_state->exception_state); +} + int32_t ExecutingContextWebFMethods::SetTimeout(ExecutingContext* context, WebFNativeFunctionContext* callback_context, int32_t timeout, diff --git a/bridge/core/dart_isolate_context.cc b/bridge/core/dart_isolate_context.cc index 3787b1e533..198b7166e2 100644 --- a/bridge/core/dart_isolate_context.cc +++ b/bridge/core/dart_isolate_context.cc @@ -3,6 +3,7 @@ */ #include "dart_isolate_context.h" +#include #include #include "defined_properties_initializer.h" #include "event_factory.h" diff --git a/bridge/core/dom/space_split_string.h b/bridge/core/dom/space_split_string.h index 154053dfbe..f7843a5ee4 100644 --- a/bridge/core/dom/space_split_string.h +++ b/bridge/core/dom/space_split_string.h @@ -5,6 +5,7 @@ #ifndef WEBF_CORE_DOM_SPACE_SPLIT_STRING_H_ #define WEBF_CORE_DOM_SPACE_SPLIT_STRING_H_ +#include #include #include #include "bindings/qjs/atomic_string.h" diff --git a/bridge/core/frame/module_callback.cc b/bridge/core/frame/module_callback.cc index c05b11d52a..0557e90e21 100644 --- a/bridge/core/frame/module_callback.cc +++ b/bridge/core/frame/module_callback.cc @@ -1,21 +1,21 @@ -/* - * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. - * Copyright (C) 2022-present The WebF authors. All rights reserved. - */ -#include "module_callback.h" - -#include - -namespace webf { - -std::shared_ptr ModuleCallback::Create(const std::shared_ptr& function) { - return std::make_shared(function); -} - -ModuleCallback::ModuleCallback(std::shared_ptr function) : function_(std::move(function)) {} - -std::shared_ptr ModuleCallback::value() { - return function_; -} - -} // namespace webf +/* + * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. + * Copyright (C) 2022-present The WebF authors. All rights reserved. + */ +#include "module_callback.h" + +#include + +namespace webf { + +std::shared_ptr ModuleCallback::Create(const std::shared_ptr& function) { + return std::make_shared(function); +} + +ModuleCallback::ModuleCallback(std::shared_ptr function) : function_(std::move(function)) {} + +std::shared_ptr ModuleCallback::value() { + return function_; +} + +} // namespace webf diff --git a/bridge/core/frame/module_callback.h b/bridge/core/frame/module_callback.h index 7e7fbc4d7a..20e6e1e771 100644 --- a/bridge/core/frame/module_callback.h +++ b/bridge/core/frame/module_callback.h @@ -1,29 +1,29 @@ -/* - * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. - * Copyright (C) 2022-present The WebF authors. All rights reserved. - */ -#ifndef BRIDGE_MODULE_CALLBACK_H -#define BRIDGE_MODULE_CALLBACK_H - -#include -#include "bindings/qjs/qjs_function.h" - -namespace webf { - -// ModuleCallback is an asynchronous callback function, usually from the 4th parameter of `webf.invokeModule` -// function. When the asynchronous operation on the Dart side ends, the callback is will called and to return to the JS -// executing environment. -class ModuleCallback { - public: - static std::shared_ptr Create(const std::shared_ptr& function); - explicit ModuleCallback(std::shared_ptr function); - - std::shared_ptr value(); - - private: - std::shared_ptr function_{nullptr}; -}; - -} // namespace webf - -#endif // BRIDGE_MODULE_CALLBACK_H +/* + * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. + * Copyright (C) 2022-present The WebF authors. All rights reserved. + */ +#ifndef BRIDGE_MODULE_CALLBACK_H +#define BRIDGE_MODULE_CALLBACK_H + +#include +#include "bindings/qjs/qjs_function.h" + +namespace webf { + +// ModuleCallback is an asynchronous callback function, usually from the 4th parameter of `webf.invokeModule` +// function. When the asynchronous operation on the Dart side ends, the callback is will called and to return to the JS +// executing environment. +class ModuleCallback { + public: + static std::shared_ptr Create(const std::shared_ptr& function); + explicit ModuleCallback(std::shared_ptr function); + + std::shared_ptr value(); + + private: + std::shared_ptr function_{nullptr}; +}; + +} // namespace webf + +#endif // BRIDGE_MODULE_CALLBACK_H diff --git a/bridge/core/frame/module_listener.cc b/bridge/core/frame/module_listener.cc index 7ac104e7a6..570cf03bae 100644 --- a/bridge/core/frame/module_listener.cc +++ b/bridge/core/frame/module_listener.cc @@ -1,21 +1,21 @@ -/* - * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. - * Copyright (C) 2022-present The WebF authors. All rights reserved. - */ -#include "module_listener.h" - -#include - -namespace webf { - -std::shared_ptr ModuleListener::Create(const std::shared_ptr& function) { - return std::make_shared(function); -} - -ModuleListener::ModuleListener(std::shared_ptr function) : function_(std::move(function)) {} - -const std::shared_ptr& ModuleListener::value() { - return function_; -} - -} // namespace webf +/* + * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. + * Copyright (C) 2022-present The WebF authors. All rights reserved. + */ +#include "module_listener.h" + +#include + +namespace webf { + +std::shared_ptr ModuleListener::Create(const std::shared_ptr& function) { + return std::make_shared(function); +} + +ModuleListener::ModuleListener(std::shared_ptr function) : function_(std::move(function)) {} + +const std::shared_ptr& ModuleListener::value() { + return function_; +} + +} // namespace webf diff --git a/bridge/core/frame/module_listener.h b/bridge/core/frame/module_listener.h index d4e2afa15b..53b0de14eb 100644 --- a/bridge/core/frame/module_listener.h +++ b/bridge/core/frame/module_listener.h @@ -1,34 +1,34 @@ -/* - * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. - * Copyright (C) 2022-present The WebF authors. All rights reserved. - */ -#ifndef BRIDGE_MODULE_LISTENER_H -#define BRIDGE_MODULE_LISTENER_H - -#include "bindings/qjs/qjs_function.h" - -namespace webf { - -class ModuleContextCoordinator; -class ModuleListenerContainer; - -// ModuleListener is an persistent callback function. Registered from user with `webf.addModuleListener` method. -// When module event triggered at dart side, All module listener will be invoked and let user to dispatch further -// operations. -class ModuleListener { - public: - static std::shared_ptr Create(const std::shared_ptr& function); - explicit ModuleListener(std::shared_ptr function); - - const std::shared_ptr& value(); - - private: - std::shared_ptr function_{nullptr}; - - friend ModuleListenerContainer; - friend ModuleContextCoordinator; -}; - -} // namespace webf - -#endif // BRIDGE_MODULE_LISTENER_H +/* + * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. + * Copyright (C) 2022-present The WebF authors. All rights reserved. + */ +#ifndef BRIDGE_MODULE_LISTENER_H +#define BRIDGE_MODULE_LISTENER_H + +#include "bindings/qjs/qjs_function.h" + +namespace webf { + +class ModuleContextCoordinator; +class ModuleListenerContainer; + +// ModuleListener is an persistent callback function. Registered from user with `webf.addModuleListener` method. +// When module event triggered at dart side, All module listener will be invoked and let user to dispatch further +// operations. +class ModuleListener { + public: + static std::shared_ptr Create(const std::shared_ptr& function); + explicit ModuleListener(std::shared_ptr function); + + const std::shared_ptr& value(); + + private: + std::shared_ptr function_{nullptr}; + + friend ModuleListenerContainer; + friend ModuleContextCoordinator; +}; + +} // namespace webf + +#endif // BRIDGE_MODULE_LISTENER_H diff --git a/bridge/core/frame/module_manager.cc b/bridge/core/frame/module_manager.cc index 9384b7dd09..f1051ffab7 100644 --- a/bridge/core/frame/module_manager.cc +++ b/bridge/core/frame/module_manager.cc @@ -33,42 +33,67 @@ NativeValue* handleInvokeModuleTransientCallback(void* ptr, if (ctx == nullptr) return nullptr; - context->dartIsolateContext()->profiler()->StartTrackAsyncEvaluation(); - context->dartIsolateContext()->profiler()->StartTrackSteps("handleInvokeModuleTransientCallback"); - - ExceptionState exception_state; - - NativeValue* return_value = nullptr; - if (errmsg != nullptr) { - ScriptValue error_object = ScriptValue::CreateErrorObject(ctx, errmsg); - ScriptValue arguments[] = {error_object}; - ScriptValue result = moduleContext->callback->value()->Invoke(ctx, ScriptValue::Empty(ctx), 1, arguments); - if (result.IsException()) { - context->HandleException(&result); + auto callback_value = moduleContext->callback->value(); + + if (auto* callback = DynamicTo(callback_value.get())) { + context->dartIsolateContext()->profiler()->StartTrackAsyncEvaluation(); + context->dartIsolateContext()->profiler()->StartTrackSteps("handleInvokeModuleTransientCallback"); + + ExceptionState exception_state; + + NativeValue* return_value = nullptr; + if (errmsg != nullptr) { + ScriptValue error_object = ScriptValue::CreateErrorObject(ctx, errmsg); + ScriptValue arguments[] = {error_object}; + ScriptValue result = callback->Invoke(ctx, ScriptValue::Empty(ctx), 1, arguments); + if (result.IsException()) { + context->HandleException(&result); + } + NativeValue native_result = result.ToNative(ctx, exception_state); + return_value = static_cast(dart_malloc(sizeof(NativeValue))); + memcpy(return_value, &native_result, sizeof(NativeValue)); + } else { + ScriptValue arguments[] = {ScriptValue::Empty(ctx), ScriptValue(ctx, *extra_data)}; + ScriptValue result = callback->Invoke(ctx, ScriptValue::Empty(ctx), 2, arguments); + if (result.IsException()) { + context->HandleException(&result); + } + NativeValue native_result = result.ToNative(ctx, exception_state); + return_value = static_cast(dart_malloc(sizeof(NativeValue))); + memcpy(return_value, &native_result, sizeof(NativeValue)); } - NativeValue native_result = result.ToNative(ctx, exception_state); - return_value = static_cast(malloc(sizeof(NativeValue))); - memcpy(return_value, &native_result, sizeof(NativeValue)); - } else { - ScriptValue arguments[] = {ScriptValue::Empty(ctx), ScriptValue(ctx, *extra_data)}; - ScriptValue result = moduleContext->callback->value()->Invoke(ctx, ScriptValue::Empty(ctx), 2, arguments); - if (result.IsException()) { - context->HandleException(&result); - } - NativeValue native_result = result.ToNative(ctx, exception_state); - return_value = static_cast(malloc(sizeof(NativeValue))); - memcpy(return_value, &native_result, sizeof(NativeValue)); - } - context->dartIsolateContext()->profiler()->FinishTrackSteps(); - context->dartIsolateContext()->profiler()->FinishTrackAsyncEvaluation(); + context->dartIsolateContext()->profiler()->FinishTrackSteps(); + context->dartIsolateContext()->profiler()->FinishTrackAsyncEvaluation(); - if (exception_state.HasException()) { - context->HandleException(exception_state); - return nullptr; - } + if (exception_state.HasException()) { + context->HandleException(exception_state); + return nullptr; + } - return return_value; + return return_value; + } else if (auto* callback = DynamicTo(callback_value.get())) { + context->dartIsolateContext()->profiler()->StartTrackAsyncEvaluation(); + context->dartIsolateContext()->profiler()->StartTrackSteps("handleInvokeModuleTransientCallback"); + + NativeValue* return_value = nullptr; + if (errmsg != nullptr) { + NativeValue error_object = Native_NewCString(errmsg); + NativeValue native_result = callback->Invoke(context, 1, &error_object); + return_value = static_cast(dart_malloc(sizeof(NativeValue))); + memcpy(return_value, &native_result, sizeof(NativeValue)); + } else { + auto params = new NativeValue[2]; + params[0] = Native_NewNull(); + params[1] = *extra_data; + NativeValue native_result = callback->Invoke(context, 2, params); + return_value = static_cast(dart_malloc(sizeof(NativeValue))); + memcpy(return_value, &native_result, sizeof(NativeValue)); + } + context->dartIsolateContext()->profiler()->FinishTrackSteps(); + context->dartIsolateContext()->profiler()->FinishTrackAsyncEvaluation(); + return return_value; + } } static void ReturnResultToDart(Dart_PersistentHandle persistent_handle, @@ -134,7 +159,7 @@ ScriptValue ModuleManager::__webf_invoke_module__(ExecutingContext* context, const AtomicString& module_name, const AtomicString& method, ScriptValue& params_value, - const std::shared_ptr& callback, + const std::shared_ptr& callback, ExceptionState& exception) { NativeValue params = params_value.ToNative(context->ctx(), exception); @@ -151,7 +176,7 @@ NativeValue* ModuleManager::__webf_invoke_module__(ExecutingContext* context, const AtomicString& module_name, const AtomicString& method, NativeValue& params, - const std::shared_ptr& callback, + const std::shared_ptr& callback, ExceptionState& exception) { if (exception.HasException()) { return nullptr; @@ -190,7 +215,7 @@ NativeValue* ModuleManager::__webf_invoke_module__(ExecutingContext* context, void ModuleManager::__webf_add_module_listener__(ExecutingContext* context, const AtomicString& module_name, - const std::shared_ptr& handler, + const std::shared_ptr& handler, ExceptionState& exception) { auto listener = ModuleListener::Create(handler); context->ModuleListeners()->AddModuleListener(module_name, listener); diff --git a/bridge/core/frame/module_manager.h b/bridge/core/frame/module_manager.h index 5276dd68ed..bad40cf9a2 100644 --- a/bridge/core/frame/module_manager.h +++ b/bridge/core/frame/module_manager.h @@ -7,7 +7,7 @@ #include "bindings/qjs/atomic_string.h" #include "bindings/qjs/exception_state.h" -#include "bindings/qjs/qjs_function.h" +#include "foundation/function.h" #include "module_callback.h" #include @@ -37,17 +37,17 @@ class ModuleManager { const AtomicString& module_name, const AtomicString& method, ScriptValue& params_value, - const std::shared_ptr& callback, + const std::shared_ptr& callback, ExceptionState& exception); static NativeValue* __webf_invoke_module__(ExecutingContext* context, const AtomicString& module_name, const AtomicString& method, NativeValue& params_value, - const std::shared_ptr& callback, + const std::shared_ptr& callback, ExceptionState& exception); static void __webf_add_module_listener__(ExecutingContext* context, const AtomicString& module_name, - const std::shared_ptr& handler, + const std::shared_ptr& handler, ExceptionState& exception); static void __webf_remove_module_listener__(ExecutingContext* context, const AtomicString& module_name, diff --git a/bridge/core/native/native_function.h b/bridge/core/native/native_function.h index a108d81332..15a50b79d1 100644 --- a/bridge/core/native/native_function.h +++ b/bridge/core/native/native_function.h @@ -15,10 +15,10 @@ namespace webf { class SharedExceptionState; typedef struct WebFNativeFunctionContext WebFNativeFunctionContext; -using WebFNativeFunctionCallback = void (*)(WebFNativeFunctionContext* callback_context, - int32_t argc, - NativeValue* argv, - SharedExceptionState* shared_exception_state); +using WebFNativeFunctionCallback = NativeValue (*)(WebFNativeFunctionContext* callback_context, + int32_t argc, + NativeValue* argv, + SharedExceptionState* shared_exception_state); using WebFNativeFunctionFreePtrFn = void (*)(WebFNativeFunctionContext* callback_context); struct WebFNativeFunctionContext : public RustReadable { @@ -44,8 +44,8 @@ class WebFNativeFunction : public Function { 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_); + NativeValue Invoke(ExecutingContext* context, int32_t argc, NativeValue* argv) { + return callback_context_->callback(callback_context_, argc, argv, shared_exception_state_); } private: diff --git a/bridge/core/page.cc b/bridge/core/page.cc index 6d04460dfd..5880f01bb3 100644 --- a/bridge/core/page.cc +++ b/bridge/core/page.cc @@ -1,300 +1,319 @@ -/* - * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. - * Copyright (C) 2022-present The WebF authors. All rights reserved. - */ -#include -#include - -#include "bindings/qjs/atomic_string.h" -#include "bindings/qjs/binding_initializer.h" -#include "core/dart_methods.h" -#include "core/dom/document.h" -#include "core/frame/window.h" -#include "core/html/html_html_element.h" -#include "core/html/parser/html_parser.h" -#include "event_factory.h" -#include "foundation/logging.h" -#include "foundation/native_value_converter.h" -#include "page.h" -#include "polyfill.h" - -namespace webf { - -ConsoleMessageHandler WebFPage::consoleMessageHandler{nullptr}; - -WebFPage::WebFPage(DartIsolateContext* dart_isolate_context, - bool is_dedicated, - size_t sync_buffer_size, - double context_id, - const JSExceptionHandler& handler) - : ownerThreadId(std::this_thread::get_id()), dart_isolate_context_(dart_isolate_context) { - context_ = new ExecutingContext( - dart_isolate_context, is_dedicated, sync_buffer_size, context_id, - [](ExecutingContext* context, const char* message) { - WEBF_LOG(ERROR) << message << std::endl; - if (context->IsContextValid()) { - context->dartMethodPtr()->onJSError(context->isDedicated(), context->contextId(), message); - } - }, - this); -} - -bool WebFPage::parseHTML(const char* code, size_t length) { - if (!context_->IsContextValid()) - return false; - - { - MemberMutationScope scope{context_}; - - auto document_element = context_->document()->documentElement(); - if (!document_element) { - return false; - } - - context_->dartIsolateContext()->profiler()->StartTrackSteps("HTMLParser::parseHTML"); - HTMLParser::parseHTML(code, length, context_->document()->documentElement()); - context_->dartIsolateContext()->profiler()->FinishTrackSteps(); - } - - context_->uiCommandBuffer()->AddCommand(UICommand::kFinishRecordingCommand, nullptr, nullptr, nullptr); - - return true; -} - -NativeValue* WebFPage::invokeModuleEvent(SharedNativeString* native_module_name, - const char* eventType, - void* ptr, - NativeValue* extra) { - if (!context_->IsContextValid()) - return nullptr; - - MemberMutationScope scope{context_}; - - JSContext* ctx = context_->ctx(); - Event* event = nullptr; - if (ptr != nullptr) { - std::string type = std::string(eventType); - auto* raw_event = static_cast(ptr); - event = EventFactory::Create(context_, AtomicString(ctx, type), raw_event); - delete raw_event; - } - - ScriptValue extraObject = ScriptValue(ctx, const_cast(*extra)); - AtomicString module_name = AtomicString( - ctx, std::unique_ptr(reinterpret_cast(native_module_name))); - auto listener = context_->ModuleListeners()->listener(module_name); - - if (listener == nullptr) { - return nullptr; - } - - ScriptValue arguments[] = {event != nullptr ? event->ToValue() : ScriptValue::Empty(ctx), extraObject}; - ScriptValue result = listener->value()->Invoke(ctx, ScriptValue::Empty(ctx), 2, arguments); - if (result.IsException()) { - context_->HandleException(&result); - return nullptr; - } - - ExceptionState exception_state; - auto* return_value = static_cast(malloc(sizeof(NativeValue))); - NativeValue tmp = result.ToNative(ctx, exception_state); - if (exception_state.HasException()) { - context_->HandleException(exception_state); - return nullptr; - } - - memcpy(return_value, &tmp, sizeof(NativeValue)); - return return_value; -} - -bool WebFPage::evaluateScript(const char* script, - uint64_t script_len, - uint8_t** parsed_bytecodes, - uint64_t* bytecode_len, - const char* url, - int startLine) { - if (!context_->IsContextValid()) - return false; - return context_->EvaluateJavaScript(script, script_len, parsed_bytecodes, bytecode_len, url, startLine); -} - -void WebFPage::evaluateScript(const char* script, size_t length, const char* url, int startLine) { - if (!context_->IsContextValid()) - return; - context_->EvaluateJavaScript(script, length, url, startLine); -} - -uint8_t* WebFPage::dumpByteCode(const char* script, size_t length, const char* url, uint64_t* byteLength) { - if (!context_->IsContextValid()) - return nullptr; - return context_->DumpByteCode(script, static_cast(length), url, byteLength); -} - -bool WebFPage::evaluateByteCode(uint8_t* bytes, size_t byteLength) { - if (!context_->IsContextValid()) - return false; - return context_->EvaluateByteCode(bytes, byteLength); -} - -std::thread::id WebFPage::currentThread() const { - return ownerThreadId; -} - -WebFPage::~WebFPage() { -#if IS_TEST - if (disposeCallback != nullptr) { - disposeCallback(this); - } -#endif - delete context_; -} - -void WebFPage::reportError(const char* errmsg) { - handler_(context_, errmsg); -} - -static void ReturnEvaluateScriptsInternal(Dart_PersistentHandle persistent_handle, - EvaluateQuickjsByteCodeCallback result_callback, - bool is_success) { - Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); - result_callback(handle, is_success ? 1 : 0); - Dart_DeletePersistentHandle_DL(persistent_handle); -} - -void WebFPage::EvaluateScriptsInternal(void* page_, - const char* code, - uint64_t code_len, - uint8_t** parsed_bytecodes, - uint64_t* bytecode_len, - const char* bundleFilename, - int32_t startLine, - int64_t profile_id, - Dart_Handle persistent_handle, - EvaluateScriptsCallback result_callback) { - auto page = reinterpret_cast(page_); - assert(std::this_thread::get_id() == page->currentThread()); - - page->dartIsolateContext()->profiler()->StartTrackEvaluation(profile_id); - - bool is_success = page->evaluateScript(code, code_len, parsed_bytecodes, bytecode_len, bundleFilename, startLine); - - page->dartIsolateContext()->profiler()->FinishTrackEvaluation(profile_id); - - page->dartIsolateContext()->dispatcher()->PostToDart(page->isDedicated(), ReturnEvaluateScriptsInternal, - persistent_handle, result_callback, is_success); -} - -static void ReturnEvaluateQuickjsByteCodeResultToDart(Dart_PersistentHandle persistent_handle, - EvaluateQuickjsByteCodeCallback result_callback, - bool is_success) { - Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); - result_callback(handle, is_success ? 1 : 0); - Dart_DeletePersistentHandle_DL(persistent_handle); -} - -void WebFPage::EvaluateQuickjsByteCodeInternal(void* page_, - uint8_t* bytes, - int32_t byteLen, - int64_t profile_id, - Dart_PersistentHandle persistent_handle, - EvaluateQuickjsByteCodeCallback result_callback) { - auto page = reinterpret_cast(page_); - assert(std::this_thread::get_id() == page->currentThread()); - - page->dartIsolateContext()->profiler()->StartTrackEvaluation(profile_id); - - bool is_success = page->evaluateByteCode(bytes, byteLen); - - page->dartIsolateContext()->profiler()->FinishTrackEvaluation(profile_id); - - page->dartIsolateContext()->dispatcher()->PostToDart(page->isDedicated(), ReturnEvaluateQuickjsByteCodeResultToDart, - persistent_handle, result_callback, is_success); -} - -static void ReturnParseHTMLToDart(Dart_PersistentHandle persistent_handle, ParseHTMLCallback result_callback) { - Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); - result_callback(handle); - Dart_DeletePersistentHandle_DL(persistent_handle); -} - -void WebFPage::ParseHTMLInternal(void* page_, - char* code, - int32_t length, - int64_t profile_id, - Dart_PersistentHandle dart_handle, - ParseHTMLCallback result_callback) { - auto page = reinterpret_cast(page_); - assert(std::this_thread::get_id() == page->currentThread()); - - page->dartIsolateContext()->profiler()->StartTrackEvaluation(profile_id); - - page->parseHTML(code, length); - dart_free(code); - - page->dartIsolateContext()->profiler()->FinishTrackEvaluation(profile_id); - - page->dartIsolateContext()->dispatcher()->PostToDart(page->isDedicated(), ReturnParseHTMLToDart, dart_handle, - result_callback); -} - -static void ReturnInvokeEventResultToDart(Dart_Handle persistent_handle, - InvokeModuleEventCallback result_callback, - webf::NativeValue* result) { - Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); - result_callback(handle, result); - Dart_DeletePersistentHandle_DL(persistent_handle); -} - -void WebFPage::InvokeModuleEventInternal(void* page_, - void* module_name, - const char* eventType, - void* event, - void* extra, - Dart_Handle persistent_handle, - InvokeModuleEventCallback result_callback) { - auto page = reinterpret_cast(page_); - auto dart_isolate_context = page->executingContext()->dartIsolateContext(); - assert(std::this_thread::get_id() == page->currentThread()); - - page->dartIsolateContext()->profiler()->StartTrackAsyncEvaluation(); - - auto* result = page->invokeModuleEvent(reinterpret_cast(module_name), eventType, event, - reinterpret_cast(extra)); - - page->dartIsolateContext()->profiler()->FinishTrackAsyncEvaluation(); - - dart_isolate_context->dispatcher()->PostToDart(page->isDedicated(), ReturnInvokeEventResultToDart, persistent_handle, - result_callback, result); -} - -static void ReturnDumpByteCodeResultToDart(Dart_Handle persistent_handle, DumpQuickjsByteCodeCallback result_callback) { - Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); - result_callback(handle); - Dart_DeletePersistentHandle_DL(persistent_handle); -} - -void WebFPage::DumpQuickJsByteCodeInternal(void* page_, - int64_t profile_id, - const char* code, - int32_t code_len, - uint8_t** parsed_bytecodes, - uint64_t* bytecode_len, - const char* url, - Dart_PersistentHandle persistent_handle, - DumpQuickjsByteCodeCallback result_callback) { - auto page = reinterpret_cast(page_); - auto dart_isolate_context = page->executingContext()->dartIsolateContext(); - - dart_isolate_context->profiler()->StartTrackEvaluation(profile_id); - - assert(std::this_thread::get_id() == page->currentThread()); - uint8_t* bytes = page->dumpByteCode(code, code_len, url, bytecode_len); - *parsed_bytecodes = bytes; - - dart_isolate_context->profiler()->FinishTrackEvaluation(profile_id); - - dart_isolate_context->dispatcher()->PostToDart(page->isDedicated(), ReturnDumpByteCodeResultToDart, persistent_handle, - result_callback); -} - -} // namespace webf +/* + * Copyright (C) 2019-2022 The Kraken authors. All rights reserved. + * Copyright (C) 2022-present The WebF authors. All rights reserved. + */ +#include +#include + +#include "bindings/qjs/atomic_string.h" +#include "bindings/qjs/binding_initializer.h" +#include "core/dart_methods.h" +#include "core/dom/document.h" +#include "core/frame/window.h" +#include "core/html/html_html_element.h" +#include "core/html/parser/html_parser.h" +#include "event_factory.h" +#include "foundation/logging.h" +#include "foundation/native_value_converter.h" +#include "page.h" +#include "polyfill.h" + +namespace webf { + +ConsoleMessageHandler WebFPage::consoleMessageHandler{nullptr}; + +WebFPage::WebFPage(DartIsolateContext* dart_isolate_context, + bool is_dedicated, + size_t sync_buffer_size, + double context_id, + const JSExceptionHandler& handler) + : ownerThreadId(std::this_thread::get_id()), dart_isolate_context_(dart_isolate_context) { + context_ = new ExecutingContext( + dart_isolate_context, is_dedicated, sync_buffer_size, context_id, + [](ExecutingContext* context, const char* message) { + WEBF_LOG(ERROR) << message << std::endl; + if (context->IsContextValid()) { + context->dartMethodPtr()->onJSError(context->isDedicated(), context->contextId(), message); + } + }, + this); +} + +bool WebFPage::parseHTML(const char* code, size_t length) { + if (!context_->IsContextValid()) + return false; + + { + MemberMutationScope scope{context_}; + + auto document_element = context_->document()->documentElement(); + if (!document_element) { + return false; + } + + context_->dartIsolateContext()->profiler()->StartTrackSteps("HTMLParser::parseHTML"); + HTMLParser::parseHTML(code, length, context_->document()->documentElement()); + context_->dartIsolateContext()->profiler()->FinishTrackSteps(); + } + + context_->uiCommandBuffer()->AddCommand(UICommand::kFinishRecordingCommand, nullptr, nullptr, nullptr); + + return true; +} + +NativeValue* WebFPage::invokeModuleEvent(SharedNativeString* native_module_name, + const char* eventType, + void* ptr, + NativeValue* extra) { + if (!context_->IsContextValid()) + return nullptr; + + MemberMutationScope scope{context_}; + + JSContext* ctx = context_->ctx(); + Event* event = nullptr; + if (ptr != nullptr) { + std::string type = std::string(eventType); + auto* raw_event = static_cast(ptr); + event = EventFactory::Create(context_, AtomicString(ctx, type), raw_event); + delete raw_event; + } + + ScriptValue extraObject = ScriptValue(ctx, const_cast(*extra)); + AtomicString module_name = AtomicString( + ctx, std::unique_ptr(reinterpret_cast(native_module_name))); + auto listener = context_->ModuleListeners()->listener(module_name); + + if (listener == nullptr) { + return nullptr; + } + + auto callback_value = listener->value(); + if (auto* callback = DynamicTo(callback_value.get())) { + ScriptValue arguments[] = {event != nullptr ? event->ToValue() : ScriptValue::Empty(ctx), extraObject}; + ScriptValue result = callback->Invoke(ctx, ScriptValue::Empty(ctx), 2, arguments); + if (result.IsException()) { + context_->HandleException(&result); + return nullptr; + } + + ExceptionState exception_state; + auto* return_value = static_cast(dart_malloc(sizeof(NativeValue))); + NativeValue tmp = result.ToNative(ctx, exception_state); + if (exception_state.HasException()) { + context_->HandleException(exception_state); + return nullptr; + } + + memcpy(return_value, &tmp, sizeof(NativeValue)); + return return_value; + } else if (auto* callback = DynamicTo(callback_value.get())) { + auto* params = new NativeValue[2]; + ExceptionState exception_state; + ScriptValue eventValue = event != nullptr ? event->ToValue() : ScriptValue::Empty(ctx); + params[0] = eventValue.ToNative(ctx, exception_state); + params[1] = *extra; + + if (exception_state.HasException()) { + context_->HandleException(exception_state); + return nullptr; + } + + NativeValue tmp = callback->Invoke(context_, 2, params); + auto* return_value = static_cast(dart_malloc(sizeof(NativeValue))); + memcpy(return_value, &tmp, sizeof(NativeValue)); + return return_value; + } +} + +bool WebFPage::evaluateScript(const char* script, + uint64_t script_len, + uint8_t** parsed_bytecodes, + uint64_t* bytecode_len, + const char* url, + int startLine) { + if (!context_->IsContextValid()) + return false; + return context_->EvaluateJavaScript(script, script_len, parsed_bytecodes, bytecode_len, url, startLine); +} + +void WebFPage::evaluateScript(const char* script, size_t length, const char* url, int startLine) { + if (!context_->IsContextValid()) + return; + context_->EvaluateJavaScript(script, length, url, startLine); +} + +uint8_t* WebFPage::dumpByteCode(const char* script, size_t length, const char* url, uint64_t* byteLength) { + if (!context_->IsContextValid()) + return nullptr; + return context_->DumpByteCode(script, static_cast(length), url, byteLength); +} + +bool WebFPage::evaluateByteCode(uint8_t* bytes, size_t byteLength) { + if (!context_->IsContextValid()) + return false; + return context_->EvaluateByteCode(bytes, byteLength); +} + +std::thread::id WebFPage::currentThread() const { + return ownerThreadId; +} + +WebFPage::~WebFPage() { +#if IS_TEST + if (disposeCallback != nullptr) { + disposeCallback(this); + } +#endif + delete context_; +} + +void WebFPage::reportError(const char* errmsg) { + handler_(context_, errmsg); +} + +static void ReturnEvaluateScriptsInternal(Dart_PersistentHandle persistent_handle, + EvaluateQuickjsByteCodeCallback result_callback, + bool is_success) { + Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); + result_callback(handle, is_success ? 1 : 0); + Dart_DeletePersistentHandle_DL(persistent_handle); +} + +void WebFPage::EvaluateScriptsInternal(void* page_, + const char* code, + uint64_t code_len, + uint8_t** parsed_bytecodes, + uint64_t* bytecode_len, + const char* bundleFilename, + int32_t startLine, + int64_t profile_id, + Dart_Handle persistent_handle, + EvaluateScriptsCallback result_callback) { + auto page = reinterpret_cast(page_); + assert(std::this_thread::get_id() == page->currentThread()); + + page->dartIsolateContext()->profiler()->StartTrackEvaluation(profile_id); + + bool is_success = page->evaluateScript(code, code_len, parsed_bytecodes, bytecode_len, bundleFilename, startLine); + + page->dartIsolateContext()->profiler()->FinishTrackEvaluation(profile_id); + + page->dartIsolateContext()->dispatcher()->PostToDart(page->isDedicated(), ReturnEvaluateScriptsInternal, + persistent_handle, result_callback, is_success); +} + +static void ReturnEvaluateQuickjsByteCodeResultToDart(Dart_PersistentHandle persistent_handle, + EvaluateQuickjsByteCodeCallback result_callback, + bool is_success) { + Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); + result_callback(handle, is_success ? 1 : 0); + Dart_DeletePersistentHandle_DL(persistent_handle); +} + +void WebFPage::EvaluateQuickjsByteCodeInternal(void* page_, + uint8_t* bytes, + int32_t byteLen, + int64_t profile_id, + Dart_PersistentHandle persistent_handle, + EvaluateQuickjsByteCodeCallback result_callback) { + auto page = reinterpret_cast(page_); + assert(std::this_thread::get_id() == page->currentThread()); + + page->dartIsolateContext()->profiler()->StartTrackEvaluation(profile_id); + + bool is_success = page->evaluateByteCode(bytes, byteLen); + + page->dartIsolateContext()->profiler()->FinishTrackEvaluation(profile_id); + + page->dartIsolateContext()->dispatcher()->PostToDart(page->isDedicated(), ReturnEvaluateQuickjsByteCodeResultToDart, + persistent_handle, result_callback, is_success); +} + +static void ReturnParseHTMLToDart(Dart_PersistentHandle persistent_handle, ParseHTMLCallback result_callback) { + Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); + result_callback(handle); + Dart_DeletePersistentHandle_DL(persistent_handle); +} + +void WebFPage::ParseHTMLInternal(void* page_, + char* code, + int32_t length, + int64_t profile_id, + Dart_PersistentHandle dart_handle, + ParseHTMLCallback result_callback) { + auto page = reinterpret_cast(page_); + assert(std::this_thread::get_id() == page->currentThread()); + + page->dartIsolateContext()->profiler()->StartTrackEvaluation(profile_id); + + page->parseHTML(code, length); + dart_free(code); + + page->dartIsolateContext()->profiler()->FinishTrackEvaluation(profile_id); + + page->dartIsolateContext()->dispatcher()->PostToDart(page->isDedicated(), ReturnParseHTMLToDart, dart_handle, + result_callback); +} + +static void ReturnInvokeEventResultToDart(Dart_Handle persistent_handle, + InvokeModuleEventCallback result_callback, + webf::NativeValue* result) { + Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); + result_callback(handle, result); + Dart_DeletePersistentHandle_DL(persistent_handle); +} + +void WebFPage::InvokeModuleEventInternal(void* page_, + void* module_name, + const char* eventType, + void* event, + void* extra, + Dart_Handle persistent_handle, + InvokeModuleEventCallback result_callback) { + auto page = reinterpret_cast(page_); + auto dart_isolate_context = page->executingContext()->dartIsolateContext(); + assert(std::this_thread::get_id() == page->currentThread()); + + page->dartIsolateContext()->profiler()->StartTrackAsyncEvaluation(); + + auto* result = page->invokeModuleEvent(reinterpret_cast(module_name), eventType, event, + reinterpret_cast(extra)); + + page->dartIsolateContext()->profiler()->FinishTrackAsyncEvaluation(); + + dart_isolate_context->dispatcher()->PostToDart(page->isDedicated(), ReturnInvokeEventResultToDart, persistent_handle, + result_callback, result); +} + +static void ReturnDumpByteCodeResultToDart(Dart_Handle persistent_handle, DumpQuickjsByteCodeCallback result_callback) { + Dart_Handle handle = Dart_HandleFromPersistent_DL(persistent_handle); + result_callback(handle); + Dart_DeletePersistentHandle_DL(persistent_handle); +} + +void WebFPage::DumpQuickJsByteCodeInternal(void* page_, + int64_t profile_id, + const char* code, + int32_t code_len, + uint8_t** parsed_bytecodes, + uint64_t* bytecode_len, + const char* url, + Dart_PersistentHandle persistent_handle, + DumpQuickjsByteCodeCallback result_callback) { + auto page = reinterpret_cast(page_); + auto dart_isolate_context = page->executingContext()->dartIsolateContext(); + + dart_isolate_context->profiler()->StartTrackEvaluation(profile_id); + + assert(std::this_thread::get_id() == page->currentThread()); + uint8_t* bytes = page->dumpByteCode(code, code_len, url, bytecode_len); + *parsed_bytecodes = bytes; + + dart_isolate_context->profiler()->FinishTrackEvaluation(profile_id); + + dart_isolate_context->dispatcher()->PostToDart(page->isDedicated(), ReturnDumpByteCodeResultToDart, persistent_handle, + result_callback); +} + +} // namespace webf diff --git a/bridge/foundation/dart_readable.cc b/bridge/foundation/dart_readable.cc index 07f76e650a..9b475e552d 100644 --- a/bridge/foundation/dart_readable.cc +++ b/bridge/foundation/dart_readable.cc @@ -32,8 +32,16 @@ void* DartReadable::operator new(std::size_t size) { return dart_malloc(size); } +void* DartReadable::operator new[](std::size_t size) { + return dart_malloc(size); +} + void DartReadable::operator delete(void* memory) noexcept { dart_free(memory); } +void DartReadable::operator delete[](void* memory) noexcept { + dart_free(memory); +} + } // namespace webf diff --git a/bridge/foundation/dart_readable.h b/bridge/foundation/dart_readable.h index 636c810487..fcc58bdc8c 100644 --- a/bridge/foundation/dart_readable.h +++ b/bridge/foundation/dart_readable.h @@ -1,24 +1,26 @@ -/* - * Copyright (C) 2022-present The WebF authors. All rights reserved. - */ - -#ifndef WEBF_DART_READABLE_H -#define WEBF_DART_READABLE_H - -#include - -namespace webf { - -void* dart_malloc(std::size_t size); -void dart_free(void* ptr); - -// Shared C struct which can be read by dart through Dart FFI. -struct DartReadable { - // Dart FFI use ole32 as it's allocator, we need to override the default allocator to compact with Dart FFI. - static void* operator new(std::size_t size); - static void operator delete(void* memory) noexcept; -}; - -} // namespace webf - -#endif // WEBF_DART_READABLE_H +/* + * Copyright (C) 2022-present The WebF authors. All rights reserved. + */ + +#ifndef WEBF_DART_READABLE_H +#define WEBF_DART_READABLE_H + +#include + +namespace webf { + +void* dart_malloc(std::size_t size); +void dart_free(void* ptr); + +// Shared C struct which can be read by dart through Dart FFI. +struct DartReadable { + // Dart FFI use ole32 as it's allocator, we need to override the default allocator to compact with Dart FFI. + static void* operator new(std::size_t size); + static void* operator new[](std::size_t size); + static void operator delete(void* memory) noexcept; + static void operator delete[](void* memory) noexcept; +}; + +} // namespace webf + +#endif // WEBF_DART_READABLE_H diff --git a/bridge/foundation/native_value.h b/bridge/foundation/native_value.h index be7ffdd164..c55499a8d0 100644 --- a/bridge/foundation/native_value.h +++ b/bridge/foundation/native_value.h @@ -46,28 +46,6 @@ struct NativeValue : public DartReadable { int32_t tag; }; -struct NativeFunctionContext; - -using CallNativeFunction = void (*)(NativeFunctionContext* functionContext, - int32_t argc, - NativeValue* argv, - NativeValue* returnValue); - -static void call_native_function(NativeFunctionContext* functionContext, - int32_t argc, - NativeValue* argv, - NativeValue* returnValue); - -struct NativeFunctionContext { - CallNativeFunction call; - NativeFunctionContext(ExecutingContext* context, JSValue callback); - ~NativeFunctionContext(); - JSValue m_callback{JS_NULL}; - ExecutingContext* m_context{nullptr}; - JSContext* m_ctx{nullptr}; - list_head link; -}; - NativeValue Native_NewNull(); NativeValue Native_NewString(SharedNativeString* string); NativeValue Native_NewCString(const std::string& string); diff --git a/bridge/foundation/rust_readable.cc b/bridge/foundation/rust_readable.cc index 8fcb9d21ce..7e00eba7b2 100644 --- a/bridge/foundation/rust_readable.cc +++ b/bridge/foundation/rust_readable.cc @@ -14,7 +14,7 @@ namespace webf { void* RustReadable::operator new(std::size_t size) { #if defined(_WIN32) - return HeapAlloc(GetProcessHeap(), HEAP_GENERATE_EXCEPTIONS, size); + return CoTaskMemAlloc(size); #else return malloc(size); #endif @@ -22,8 +22,9 @@ void* RustReadable::operator new(std::size_t size) { void RustReadable::operator delete(void* memory) noexcept { #if defined(_WIN32) - HeapFree(GetProcessHeap(), 0, memory); + return CoTaskMemFree(memory); #else + return free(memory); #endif } diff --git a/bridge/foundation/ui_command_strategy.cc b/bridge/foundation/ui_command_strategy.cc index 8fddd6ca32..ddb56edace 100644 --- a/bridge/foundation/ui_command_strategy.cc +++ b/bridge/foundation/ui_command_strategy.cc @@ -4,6 +4,7 @@ #include "ui_command_strategy.h" #include +#include #include "core/binding_object.h" #include "logging.h" #include "shared_ui_command.h" diff --git a/bridge/include/plugin_api/executing_context.h b/bridge/include/plugin_api/executing_context.h index 9eeebffe91..ac39e43886 100644 --- a/bridge/include/plugin_api/executing_context.h +++ b/bridge/include/plugin_api/executing_context.h @@ -8,6 +8,7 @@ #include "core/native/native_function.h" #include "document.h" #include "exception_state.h" +#include "foundation/native_value.h" #include "window.h" namespace webf { @@ -20,6 +21,16 @@ using PublicContextGetDocument = WebFValue (*)( using PublicContextGetWindow = WebFValue (*)(ExecutingContext*); using PublicContextGetExceptionState = WebFValue (*)(); using PublicFinishRecordingUIOperations = void (*)(ExecutingContext* context); +using PublicWebFInvokeModule = NativeValue (*)(ExecutingContext*, const char*, const char*, SharedExceptionState*); +using PublicWebFInvokeModuleWithParams = + NativeValue (*)(ExecutingContext*, const char*, const char*, NativeValue*, SharedExceptionState*); +using PublicWebFInvokeModuleWithParamsAndCallback = NativeValue (*)(ExecutingContext*, + const char*, + const char*, + NativeValue*, + WebFNativeFunctionContext*, + SharedExceptionState*); +using PublicWebFLocationReload = void (*)(ExecutingContext*, SharedExceptionState*); using PublicContextSetTimeout = int32_t (*)(ExecutingContext*, WebFNativeFunctionContext*, int32_t, @@ -38,6 +49,22 @@ struct ExecutingContextWebFMethods { static WebFValue window(ExecutingContext* context); static WebFValue CreateExceptionState(); static void FinishRecordingUIOperations(ExecutingContext* context); + static NativeValue WebFInvokeModule(ExecutingContext* context, + const char* module_name, + const char* method, + SharedExceptionState* shared_exception_state); + static NativeValue WebFInvokeModuleWithParams(ExecutingContext* context, + const char* module_name, + const char* method, + NativeValue* params, + SharedExceptionState* shared_exception_state); + static NativeValue WebFInvokeModuleWithParamsAndCallback(ExecutingContext* context, + const char* module_name, + const char* method, + NativeValue* params, + WebFNativeFunctionContext* callback_context, + SharedExceptionState* shared_exception_state); + static void WebFLocationReload(ExecutingContext* context, SharedExceptionState* shared_exception_state); static int32_t SetTimeout(ExecutingContext* context, WebFNativeFunctionContext* callback_context, int32_t timeout, @@ -56,6 +83,11 @@ struct ExecutingContextWebFMethods { PublicContextGetWindow context_get_window{window}; PublicContextGetExceptionState context_get_exception_state{CreateExceptionState}; PublicFinishRecordingUIOperations context_finish_recording_ui_operations{FinishRecordingUIOperations}; + PublicWebFInvokeModule context_webf_invoke_module{WebFInvokeModule}; + PublicWebFInvokeModuleWithParams context_webf_invoke_module_with_params{WebFInvokeModuleWithParams}; + PublicWebFInvokeModuleWithParamsAndCallback context_webf_invoke_module_with_params_and_callback{ + WebFInvokeModuleWithParamsAndCallback}; + PublicWebFLocationReload context_webf_location_reload{WebFLocationReload}; PublicContextSetTimeout context_set_timeout{SetTimeout}; PublicContextSetInterval context_set_interval{SetInterval}; PublicContextClearTimeout context_clear_timeout{ClearTimeout}; diff --git a/bridge/rusty_webf_sys/Cargo.toml b/bridge/rusty_webf_sys/Cargo.toml index 4fe851bce0..633aca08d0 100644 --- a/bridge/rusty_webf_sys/Cargo.toml +++ b/bridge/rusty_webf_sys/Cargo.toml @@ -15,5 +15,5 @@ libc = "0.2.0" [dependencies.windows] version = "0.58.0" features = [ - "Win32_System_Memory" -] \ No newline at end of file + "Win32_System_Com", +] diff --git a/bridge/rusty_webf_sys/src/character_data.rs b/bridge/rusty_webf_sys/src/dom/character_data.rs similarity index 100% rename from bridge/rusty_webf_sys/src/character_data.rs rename to bridge/rusty_webf_sys/src/dom/character_data.rs diff --git a/bridge/rusty_webf_sys/src/comment.rs b/bridge/rusty_webf_sys/src/dom/comment.rs similarity index 100% rename from bridge/rusty_webf_sys/src/comment.rs rename to bridge/rusty_webf_sys/src/dom/comment.rs diff --git a/bridge/rusty_webf_sys/src/container_node.rs b/bridge/rusty_webf_sys/src/dom/container_node.rs similarity index 100% rename from bridge/rusty_webf_sys/src/container_node.rs rename to bridge/rusty_webf_sys/src/dom/container_node.rs diff --git a/bridge/rusty_webf_sys/src/document.rs b/bridge/rusty_webf_sys/src/dom/document.rs similarity index 100% rename from bridge/rusty_webf_sys/src/document.rs rename to bridge/rusty_webf_sys/src/dom/document.rs diff --git a/bridge/rusty_webf_sys/src/document_fragment.rs b/bridge/rusty_webf_sys/src/dom/document_fragment.rs similarity index 100% rename from bridge/rusty_webf_sys/src/document_fragment.rs rename to bridge/rusty_webf_sys/src/dom/document_fragment.rs diff --git a/bridge/rusty_webf_sys/src/element.rs b/bridge/rusty_webf_sys/src/dom/element.rs similarity index 100% rename from bridge/rusty_webf_sys/src/element.rs rename to bridge/rusty_webf_sys/src/dom/element.rs diff --git a/bridge/rusty_webf_sys/src/add_event_listener_options.rs b/bridge/rusty_webf_sys/src/dom/events/add_event_listener_options.rs similarity index 100% rename from bridge/rusty_webf_sys/src/add_event_listener_options.rs rename to bridge/rusty_webf_sys/src/dom/events/add_event_listener_options.rs diff --git a/bridge/rusty_webf_sys/src/custom_event.rs b/bridge/rusty_webf_sys/src/dom/events/custom_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/custom_event.rs rename to bridge/rusty_webf_sys/src/dom/events/custom_event.rs diff --git a/bridge/rusty_webf_sys/src/event.rs b/bridge/rusty_webf_sys/src/dom/events/event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/event.rs rename to bridge/rusty_webf_sys/src/dom/events/event.rs diff --git a/bridge/rusty_webf_sys/src/event_init.rs b/bridge/rusty_webf_sys/src/dom/events/event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/event_init.rs rename to bridge/rusty_webf_sys/src/dom/events/event_init.rs diff --git a/bridge/rusty_webf_sys/src/event_listener_options.rs b/bridge/rusty_webf_sys/src/dom/events/event_listener_options.rs similarity index 100% rename from bridge/rusty_webf_sys/src/event_listener_options.rs rename to bridge/rusty_webf_sys/src/dom/events/event_listener_options.rs diff --git a/bridge/rusty_webf_sys/src/event_target.rs b/bridge/rusty_webf_sys/src/dom/events/event_target.rs similarity index 100% rename from bridge/rusty_webf_sys/src/event_target.rs rename to bridge/rusty_webf_sys/src/dom/events/event_target.rs diff --git a/bridge/rusty_webf_sys/src/dom/events/mod.rs b/bridge/rusty_webf_sys/src/dom/events/mod.rs new file mode 100644 index 0000000000..e95685d5e3 --- /dev/null +++ b/bridge/rusty_webf_sys/src/dom/events/mod.rs @@ -0,0 +1,16 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ +pub mod add_event_listener_options; +pub mod custom_event; +pub mod event_init; +pub mod event_listener_options; +pub mod event_target; +pub mod event; + +pub use add_event_listener_options::*; +pub use custom_event::*; +pub use event_init::*; +pub use event_listener_options::*; +pub use event_target::*; +pub use event::*; diff --git a/bridge/rusty_webf_sys/src/dom/mod.rs b/bridge/rusty_webf_sys/src/dom/mod.rs new file mode 100644 index 0000000000..e7e42e4a7b --- /dev/null +++ b/bridge/rusty_webf_sys/src/dom/mod.rs @@ -0,0 +1,26 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ +pub mod events; +pub mod character_data; +pub mod comment; +pub mod container_node; +pub mod document_fragment; +pub mod document; +pub mod element; +pub mod node; +pub mod scroll_options; +pub mod scroll_to_options; +pub mod text; + +pub use events::*; +pub use character_data::*; +pub use comment::*; +pub use container_node::*; +pub use document_fragment::*; +pub use document::*; +pub use element::*; +pub use node::*; +pub use scroll_options::*; +pub use scroll_to_options::*; +pub use text::*; diff --git a/bridge/rusty_webf_sys/src/node.rs b/bridge/rusty_webf_sys/src/dom/node.rs similarity index 100% rename from bridge/rusty_webf_sys/src/node.rs rename to bridge/rusty_webf_sys/src/dom/node.rs diff --git a/bridge/rusty_webf_sys/src/scroll_options.rs b/bridge/rusty_webf_sys/src/dom/scroll_options.rs similarity index 100% rename from bridge/rusty_webf_sys/src/scroll_options.rs rename to bridge/rusty_webf_sys/src/dom/scroll_options.rs diff --git a/bridge/rusty_webf_sys/src/scroll_to_options.rs b/bridge/rusty_webf_sys/src/dom/scroll_to_options.rs similarity index 100% rename from bridge/rusty_webf_sys/src/scroll_to_options.rs rename to bridge/rusty_webf_sys/src/dom/scroll_to_options.rs diff --git a/bridge/rusty_webf_sys/src/text.rs b/bridge/rusty_webf_sys/src/dom/text.rs similarity index 100% rename from bridge/rusty_webf_sys/src/text.rs rename to bridge/rusty_webf_sys/src/dom/text.rs diff --git a/bridge/rusty_webf_sys/src/animation_event.rs b/bridge/rusty_webf_sys/src/events/animation_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/animation_event.rs rename to bridge/rusty_webf_sys/src/events/animation_event.rs diff --git a/bridge/rusty_webf_sys/src/animation_event_init.rs b/bridge/rusty_webf_sys/src/events/animation_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/animation_event_init.rs rename to bridge/rusty_webf_sys/src/events/animation_event_init.rs diff --git a/bridge/rusty_webf_sys/src/close_event.rs b/bridge/rusty_webf_sys/src/events/close_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/close_event.rs rename to bridge/rusty_webf_sys/src/events/close_event.rs diff --git a/bridge/rusty_webf_sys/src/close_event_init.rs b/bridge/rusty_webf_sys/src/events/close_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/close_event_init.rs rename to bridge/rusty_webf_sys/src/events/close_event_init.rs diff --git a/bridge/rusty_webf_sys/src/focus_event.rs b/bridge/rusty_webf_sys/src/events/focus_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/focus_event.rs rename to bridge/rusty_webf_sys/src/events/focus_event.rs diff --git a/bridge/rusty_webf_sys/src/focus_event_init.rs b/bridge/rusty_webf_sys/src/events/focus_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/focus_event_init.rs rename to bridge/rusty_webf_sys/src/events/focus_event_init.rs diff --git a/bridge/rusty_webf_sys/src/gesture_event.rs b/bridge/rusty_webf_sys/src/events/gesture_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/gesture_event.rs rename to bridge/rusty_webf_sys/src/events/gesture_event.rs diff --git a/bridge/rusty_webf_sys/src/gesture_event_init.rs b/bridge/rusty_webf_sys/src/events/gesture_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/gesture_event_init.rs rename to bridge/rusty_webf_sys/src/events/gesture_event_init.rs diff --git a/bridge/rusty_webf_sys/src/hashchange_event.rs b/bridge/rusty_webf_sys/src/events/hashchange_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/hashchange_event.rs rename to bridge/rusty_webf_sys/src/events/hashchange_event.rs diff --git a/bridge/rusty_webf_sys/src/hashchange_event_init.rs b/bridge/rusty_webf_sys/src/events/hashchange_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/hashchange_event_init.rs rename to bridge/rusty_webf_sys/src/events/hashchange_event_init.rs diff --git a/bridge/rusty_webf_sys/src/input_event.rs b/bridge/rusty_webf_sys/src/events/input_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/input_event.rs rename to bridge/rusty_webf_sys/src/events/input_event.rs diff --git a/bridge/rusty_webf_sys/src/input_event_init.rs b/bridge/rusty_webf_sys/src/events/input_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/input_event_init.rs rename to bridge/rusty_webf_sys/src/events/input_event_init.rs diff --git a/bridge/rusty_webf_sys/src/intersection_change_event.rs b/bridge/rusty_webf_sys/src/events/intersection_change_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/intersection_change_event.rs rename to bridge/rusty_webf_sys/src/events/intersection_change_event.rs diff --git a/bridge/rusty_webf_sys/src/intersection_change_event_init.rs b/bridge/rusty_webf_sys/src/events/intersection_change_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/intersection_change_event_init.rs rename to bridge/rusty_webf_sys/src/events/intersection_change_event_init.rs diff --git a/bridge/rusty_webf_sys/src/keyboard_event_init.rs b/bridge/rusty_webf_sys/src/events/keyboard_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/keyboard_event_init.rs rename to bridge/rusty_webf_sys/src/events/keyboard_event_init.rs diff --git a/bridge/rusty_webf_sys/src/events/mod.rs b/bridge/rusty_webf_sys/src/events/mod.rs new file mode 100644 index 0000000000..a854e34648 --- /dev/null +++ b/bridge/rusty_webf_sys/src/events/mod.rs @@ -0,0 +1,50 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ +pub mod animation_event_init; +pub mod animation_event; +pub mod close_event_init; +pub mod close_event; +pub mod focus_event_init; +pub mod focus_event; +pub mod gesture_event_init; +pub mod gesture_event; +pub mod hashchange_event_init; +pub mod hashchange_event; +pub mod input_event_init; +pub mod input_event; +pub mod intersection_change_event_init; +pub mod intersection_change_event; +pub mod keyboard_event_init; +pub mod mouse_event_init; +pub mod mouse_event; +pub mod pointer_event_init; +pub mod pointer_event; +pub mod transition_event_init; +pub mod transition_event; +pub mod ui_event_init; +pub mod ui_event; + +pub use animation_event_init::*; +pub use animation_event::*; +pub use close_event_init::*; +pub use close_event::*; +pub use focus_event_init::*; +pub use focus_event::*; +pub use gesture_event_init::*; +pub use gesture_event::*; +pub use hashchange_event_init::*; +pub use hashchange_event::*; +pub use input_event_init::*; +pub use input_event::*; +pub use intersection_change_event_init::*; +pub use intersection_change_event::*; +pub use keyboard_event_init::*; +pub use mouse_event_init::*; +pub use mouse_event::*; +pub use pointer_event_init::*; +pub use pointer_event::*; +pub use transition_event_init::*; +pub use transition_event::*; +pub use ui_event_init::*; +pub use ui_event::*; diff --git a/bridge/rusty_webf_sys/src/mouse_event.rs b/bridge/rusty_webf_sys/src/events/mouse_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/mouse_event.rs rename to bridge/rusty_webf_sys/src/events/mouse_event.rs diff --git a/bridge/rusty_webf_sys/src/mouse_event_init.rs b/bridge/rusty_webf_sys/src/events/mouse_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/mouse_event_init.rs rename to bridge/rusty_webf_sys/src/events/mouse_event_init.rs diff --git a/bridge/rusty_webf_sys/src/pointer_event.rs b/bridge/rusty_webf_sys/src/events/pointer_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/pointer_event.rs rename to bridge/rusty_webf_sys/src/events/pointer_event.rs diff --git a/bridge/rusty_webf_sys/src/pointer_event_init.rs b/bridge/rusty_webf_sys/src/events/pointer_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/pointer_event_init.rs rename to bridge/rusty_webf_sys/src/events/pointer_event_init.rs diff --git a/bridge/rusty_webf_sys/src/transition_event.rs b/bridge/rusty_webf_sys/src/events/transition_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/transition_event.rs rename to bridge/rusty_webf_sys/src/events/transition_event.rs diff --git a/bridge/rusty_webf_sys/src/transition_event_init.rs b/bridge/rusty_webf_sys/src/events/transition_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/transition_event_init.rs rename to bridge/rusty_webf_sys/src/events/transition_event_init.rs diff --git a/bridge/rusty_webf_sys/src/ui_event.rs b/bridge/rusty_webf_sys/src/events/ui_event.rs similarity index 100% rename from bridge/rusty_webf_sys/src/ui_event.rs rename to bridge/rusty_webf_sys/src/events/ui_event.rs diff --git a/bridge/rusty_webf_sys/src/ui_event_init.rs b/bridge/rusty_webf_sys/src/events/ui_event_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/ui_event_init.rs rename to bridge/rusty_webf_sys/src/events/ui_event_init.rs diff --git a/bridge/rusty_webf_sys/src/executing_context.rs b/bridge/rusty_webf_sys/src/executing_context.rs index 82253e7ca8..4a43a8851d 100644 --- a/bridge/rusty_webf_sys/src/executing_context.rs +++ b/bridge/rusty_webf_sys/src/executing_context.rs @@ -3,6 +3,8 @@ */ use std::ffi::*; +use native_value::NativeValue; + use crate::*; #[repr(C)] @@ -11,7 +13,11 @@ pub struct ExecutingContextRustMethods { pub get_document: extern "C" fn(*const OpaquePtr) -> RustValue, pub get_window: extern "C" fn(*const OpaquePtr) -> RustValue, pub create_exception_state: extern "C" fn() -> RustValue, - pub finish_recording_ui_operations: extern "C" fn(executing_context: *const OpaquePtr) -> c_void, + pub finish_recording_ui_operations: extern "C" fn(*const OpaquePtr) -> c_void, + pub webf_invoke_module: extern "C" fn(*const OpaquePtr, *const c_char, *const c_char, *const OpaquePtr) -> NativeValue, + pub webf_invoke_module_with_params: extern "C" fn(*const OpaquePtr, *const c_char, *const c_char, *const NativeValue, *const OpaquePtr) -> NativeValue, + pub webf_invoke_module_with_params_and_callback: extern "C" fn(*const OpaquePtr, *const c_char, *const c_char, *const NativeValue, *const WebFNativeFunctionContext, *const OpaquePtr) -> NativeValue, + pub webf_location_reload: extern "C" fn(*const OpaquePtr, exception_state: *const OpaquePtr) -> c_void, pub set_timeout: extern "C" fn(*const OpaquePtr, *const WebFNativeFunctionContext, c_int, *const OpaquePtr) -> c_int, pub set_interval: extern "C" fn(*const OpaquePtr, *const WebFNativeFunctionContext, c_int, *const OpaquePtr) -> c_int, pub clear_timeout: extern "C" fn(*const OpaquePtr, c_int, *const OpaquePtr), @@ -74,6 +80,22 @@ impl ExecutingContext { return Document::initialize::(result.value, self, result.method_pointer, result.status); } + pub fn navigator(&self) -> Navigator { + Navigator::initialize(self) + } + + pub fn async_storage(&self) -> AsyncStorage { + AsyncStorage::initialize(self) + } + + pub fn local_storage(&self) -> Storage { + Storage::initialize(self, "LocalStorage") + } + + pub fn session_storage(&self) -> Storage { + Storage::initialize(self, "SessionStorage") + } + pub fn create_exception_state(&self) -> ExceptionState { let result = unsafe { ((*self.method_pointer).create_exception_state)() @@ -81,6 +103,70 @@ impl ExecutingContext { ExceptionState::initialize(result.value, result.method_pointer) } + pub fn webf_invoke_module(&self, module_name: &str, method: &str, exception_state: &ExceptionState) -> Result { + let module_name = CString::new(module_name).unwrap(); + let method = CString::new(method).unwrap(); + let result = unsafe { + ((*self.method_pointer).webf_invoke_module)(self.ptr, module_name.as_ptr(), method.as_ptr(), exception_state.ptr) + }; + + if exception_state.has_exception() { + return Err(exception_state.stringify(self)); + } + + Ok(result) + } + + pub fn webf_invoke_module_with_params(&self, module_name: &str, method: &str, params: &NativeValue, exception_state: &ExceptionState) -> Result { + let module_name = CString::new(module_name).unwrap(); + let method = CString::new(method).unwrap(); + let result = unsafe { + ((*self.method_pointer).webf_invoke_module_with_params)(self.ptr, module_name.as_ptr(), method.as_ptr(), params, exception_state.ptr) + }; + + if exception_state.has_exception() { + return Err(exception_state.stringify(self)); + } + + Ok(result) + } + + pub fn webf_invoke_module_with_params_and_callback(&self, module_name: &str, method: &str, params: &NativeValue, callback: WebFNativeFunction, exception_state: &ExceptionState) -> Result { + let module_name = CString::new(module_name).unwrap(); + let method = CString::new(method).unwrap(); + + let callback_data = Box::new(WebFNativeFunctionContextData { + func: callback, + }); + let callback_context_data_ptr = Box::into_raw(callback_data); + let callback_context = Box::new(WebFNativeFunctionContext { + callback: invoke_webf_native_function, + free_ptr: release_webf_native_function, + ptr: callback_context_data_ptr, + }); + let callback_context_ptr = Box::into_raw(callback_context); + + let result = unsafe { + (((*self.method_pointer).webf_invoke_module_with_params_and_callback))(self.ptr, module_name.as_ptr(), method.as_ptr(), params, callback_context_ptr, exception_state.ptr) + }; + + if exception_state.has_exception() { + unsafe { + let _ = Box::from_raw(callback_context_ptr); + let _ = Box::from_raw(callback_context_data_ptr); + } + return Err(exception_state.stringify(self)); + } + + Ok(result) + } + + pub fn webf_location_reload(&self, exception_state: &ExceptionState) { + unsafe { + ((*self.method_pointer).webf_location_reload)(self.ptr, exception_state.ptr); + } + } + pub fn set_timeout_with_callback(&self, callback: TimeoutCallback, exception_state: &ExceptionState) -> Result { self.set_timeout_with_callback_and_timeout(callback, 0, exception_state) } @@ -89,9 +175,10 @@ impl ExecutingContext { let general_callback: WebFNativeFunction = Box::new(move |argc, argv| { if argc != 0 { println!("Invalid argument count for timeout callback"); - return; + return NativeValue::new_null(); } callback(); + NativeValue::new_null() }); let callback_data = Box::new(WebFNativeFunctionContextData { @@ -128,9 +215,10 @@ impl ExecutingContext { let general_callback: WebFNativeFunction = Box::new(move |argc, argv| { if argc != 0 { println!("Invalid argument count for interval callback"); - return; + return NativeValue::new_null(); } callback(); + NativeValue::new_null() }); let callback_data = Box::new(WebFNativeFunctionContextData { diff --git a/bridge/rusty_webf_sys/src/frame/async_storage.rs b/bridge/rusty_webf_sys/src/frame/async_storage.rs new file mode 100644 index 0000000000..aa6eb50446 --- /dev/null +++ b/bridge/rusty_webf_sys/src/frame/async_storage.rs @@ -0,0 +1,74 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ + +use crate::*; + +pub type GetItemCallback = Box, String>)>; +pub type SetItemCallback = Box, String>)>; + +pub struct AsyncStorage { + context: *const ExecutingContext, +} + +impl AsyncStorage { + pub fn initialize(context: *const ExecutingContext) -> AsyncStorage { + AsyncStorage { + context, + } + } + + pub fn context<'a>(&self) -> &'a ExecutingContext { + assert!(!self.context.is_null(), "Context PTR must not be null"); + unsafe { &*self.context } + } + + pub fn get_item(&self, key: &str, callback: GetItemCallback, exception_state: &ExceptionState) { + let key_string = NativeValue::new_string(key); + let general_callback: WebFNativeFunction = Box::new(move |argc, argv| { + if argc == 1 { + let error_string = unsafe { (*argv).clone() }; + let error_string = error_string.to_string(); + callback(Err(error_string)); + return NativeValue::new_null(); + } + if argc == 2 { + let item_string = unsafe { (*argv.wrapping_add(1)).clone() }; + if item_string.is_null() { + callback(Ok(None)); + return NativeValue::new_null(); + } + let item_string = item_string.to_string(); + callback(Ok(Some(item_string))); + return NativeValue::new_null(); + } + println!("Invalid argument count for async storage callback"); + NativeValue::new_null() + }); + self.context().webf_invoke_module_with_params_and_callback("AsyncStorage", "getItem", &key_string, general_callback, exception_state).unwrap(); + } + + pub fn set_item(&self, key: &str, value: &str, callback: SetItemCallback, exception_state: &ExceptionState) { + let key_string = NativeValue::new_string(key); + let value_string = NativeValue::new_string(value); + let params_vec = vec![key_string, value_string]; + let params = NativeValue::new_list(params_vec); + let general_callback: WebFNativeFunction = Box::new(move |argc, argv| { + if argc == 1 { + let error_string = unsafe { (*argv).clone() }; + let error_string = error_string.to_string(); + callback(Err(error_string)); + return NativeValue::new_null(); + } + if argc == 2 { + let result = unsafe { (*argv.wrapping_add(1)).clone() }; + let result = result.to_string(); + callback(Ok(Some(result))); + return NativeValue::new_null(); + } + println!("Invalid argument count for async storage callback"); + NativeValue::new_null() + }); + self.context().webf_invoke_module_with_params_and_callback("AsyncStorage", "setItem", ¶ms, general_callback, exception_state).unwrap(); + } +} diff --git a/bridge/rusty_webf_sys/src/frame/legacy/location.rs b/bridge/rusty_webf_sys/src/frame/legacy/location.rs new file mode 100644 index 0000000000..a83935449e --- /dev/null +++ b/bridge/rusty_webf_sys/src/frame/legacy/location.rs @@ -0,0 +1,88 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ + +use std::ffi::*; +use crate::*; + +pub struct Location { + context: *const ExecutingContext, +} + +impl Location { + pub fn initialize(context: *const ExecutingContext) -> Location { + Location { + context + } + } + + pub fn context<'a>(&self) -> &'a ExecutingContext { + assert!(!self.context.is_null(), "Context PTR must not be null"); + unsafe { &*self.context } + } + + pub fn href(&self, exception_state: &ExceptionState) -> String { + let href_string = self.context().webf_invoke_module("Location", "href", exception_state).unwrap(); + href_string.to_string() + } + + pub fn set_href(&self, href: &str, exception_state: &ExceptionState) { + let href_string_native_value = NativeValue::new_string(href); + self.context().webf_invoke_module_with_params("Navigation", "goTo", &href_string_native_value, exception_state); + } + + pub fn origin(&self, exception_state: &ExceptionState) -> String { + let origin_string = self.context().webf_invoke_module("Location", "origin", exception_state).unwrap(); + origin_string.to_string() + } + + pub fn protocol(&self, exception_state: &ExceptionState) -> String { + let protocol_string = self.context().webf_invoke_module("Location", "protocol", exception_state).unwrap(); + protocol_string.to_string() + } + + pub fn host(&self, exception_state: &ExceptionState) -> String { + let host_string = self.context().webf_invoke_module("Location", "host", exception_state).unwrap(); + host_string.to_string() + } + + pub fn hostname(&self, exception_state: &ExceptionState) -> String { + let hostname_string = self.context().webf_invoke_module("Location", "hostname", exception_state).unwrap(); + hostname_string.to_string() + } + + pub fn port(&self, exception_state: &ExceptionState) -> String { + let port_string = self.context().webf_invoke_module("Location", "port", exception_state).unwrap(); + port_string.to_string() + } + + pub fn pathname(&self, exception_state: &ExceptionState) -> String { + let pathname_string = self.context().webf_invoke_module("Location", "pathname", exception_state).unwrap(); + pathname_string.to_string() + } + + pub fn search(&self, exception_state: &ExceptionState) -> String { + let search_string = self.context().webf_invoke_module("Location", "search", exception_state).unwrap(); + search_string.to_string() + } + + pub fn hash(&self, exception_state: &ExceptionState) -> String { + let hash_string = self.context().webf_invoke_module("Location", "hash", exception_state).unwrap(); + hash_string.to_string() + } + + pub fn assign(&self, url: &str, exception_state: &ExceptionState) { + let url_string_native_value = NativeValue::new_string(url); + self.context().webf_invoke_module_with_params("Navigation", "goTo", &url_string_native_value, exception_state); + } + + pub fn reload(&self, exception_state: &ExceptionState) { + self.context().webf_location_reload(exception_state); + } + + pub fn replace(&self, url: &str, exception_state: &ExceptionState) { + let url_string_native_value = NativeValue::new_string(url); + self.context().webf_invoke_module_with_params("Navigation", "goTo", &url_string_native_value, exception_state); + } + +} diff --git a/bridge/rusty_webf_sys/src/frame/legacy/mod.rs b/bridge/rusty_webf_sys/src/frame/legacy/mod.rs new file mode 100644 index 0000000000..fb9dc8a223 --- /dev/null +++ b/bridge/rusty_webf_sys/src/frame/legacy/mod.rs @@ -0,0 +1,6 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ +pub mod location; + +pub use location::*; diff --git a/bridge/rusty_webf_sys/src/frame/mod.rs b/bridge/rusty_webf_sys/src/frame/mod.rs new file mode 100644 index 0000000000..f4de0700cc --- /dev/null +++ b/bridge/rusty_webf_sys/src/frame/mod.rs @@ -0,0 +1,14 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ +pub mod async_storage; +pub mod navigator; +pub mod window; +pub mod storage; +pub mod legacy; + +pub use async_storage::*; +pub use navigator::*; +pub use window::*; +pub use storage::*; +pub use legacy::*; diff --git a/bridge/rusty_webf_sys/src/frame/navigator.rs b/bridge/rusty_webf_sys/src/frame/navigator.rs new file mode 100644 index 0000000000..8927947bd7 --- /dev/null +++ b/bridge/rusty_webf_sys/src/frame/navigator.rs @@ -0,0 +1,58 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ + +use crate::*; + +pub struct Navigator { + context: *const ExecutingContext, +} + +impl Navigator { + pub fn initialize(context: *const ExecutingContext) -> Navigator { + Navigator { + context + } + } + + pub fn context<'a>(&self) -> &'a ExecutingContext { + assert!(!self.context.is_null(), "Context PTR must not be null"); + unsafe { &*self.context } + } + + pub fn user_agent(&self, exception_state: &ExceptionState) -> String { + let ua_string = self.context().webf_invoke_module("Navigator", "getUserAgent", exception_state).unwrap(); + ua_string.to_string() + } + + pub fn platform(&self, exception_state: &ExceptionState) -> String { + let platform_string = self.context().webf_invoke_module("Navigator", "getPlatform", exception_state).unwrap(); + platform_string.to_string() + } + + pub fn language(&self, exception_state: &ExceptionState) -> String { + let language_string = self.context().webf_invoke_module("Navigator", "getLanguage", exception_state).unwrap(); + language_string.to_string() + } + + pub fn languages(&self, exception_state: &ExceptionState) -> String { + let languages_string = self.context().webf_invoke_module("Navigator", "getLanguages", exception_state).unwrap(); + languages_string.to_string() + } + + pub fn app_name(&self, exception_state: &ExceptionState) -> String { + let app_name_string = self.context().webf_invoke_module("Navigator", "getAppName", exception_state).unwrap(); + app_name_string.to_string() + } + + pub fn app_version(&self, exception_state: &ExceptionState) -> String { + let app_version_string = self.context().webf_invoke_module("Navigator", "getAppVersion", exception_state).unwrap(); + app_version_string.to_string() + } + + pub fn hardware_concurrency(&self, exception_state: &ExceptionState) -> i32 { + let hardware_concurrency = self.context().webf_invoke_module("Navigator", "getHardwareConcurrency", exception_state).unwrap(); + let concurrency_string = hardware_concurrency.to_string(); + i32::from_str_radix(&concurrency_string, 10).unwrap() + } +} diff --git a/bridge/rusty_webf_sys/src/frame/storage.rs b/bridge/rusty_webf_sys/src/frame/storage.rs new file mode 100644 index 0000000000..be86479701 --- /dev/null +++ b/bridge/rusty_webf_sys/src/frame/storage.rs @@ -0,0 +1,79 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ + +use crate::*; + +pub struct Storage { + context: *const ExecutingContext, + module_name: String, +} + +impl Storage { + pub fn initialize(context: *const ExecutingContext, module_name: &str) -> Storage { + Storage { + context, + module_name: module_name.to_string(), + } + } + + pub fn context<'a>(&self) -> &'a ExecutingContext { + assert!(!self.context.is_null(), "Context PTR must not be null"); + unsafe { &*self.context } + } + + pub fn get_item(&self, key: &str, exception_state: &ExceptionState) -> Result, String> { + let key_string = NativeValue::new_string(key); + let item_string = self.context().webf_invoke_module_with_params(&self.module_name, "getItem", &key_string, exception_state).unwrap(); + + if exception_state.has_exception() { + return Err(exception_state.stringify(self.context())); + } + + if item_string.is_null() { + return Ok(None); + } + Ok(Some(item_string.to_string())) + } + + pub fn set_item(&self, key: &str, value: &str, exception_state: &ExceptionState) -> Result<(), String> { + let key_string = NativeValue::new_string(key); + let value_string = NativeValue::new_string(value); + let params_vec = vec![key_string, value_string]; + let params = NativeValue::new_list(params_vec); + + self.context().webf_invoke_module_with_params(&self.module_name, "setItem", ¶ms, exception_state); + + if exception_state.has_exception() { + return Err(exception_state.stringify(self.context())); + } + + Ok(()) + } + + pub fn remove_item(&self, key: &str, exception_state: &ExceptionState) { + let key_string = NativeValue::new_string(key); + self.context().webf_invoke_module_with_params(&self.module_name, "removeItem", &key_string, exception_state); + } + + pub fn clear(&self, exception_state: &ExceptionState) { + self.context().webf_invoke_module(&self.module_name, "clear", exception_state); + } + + pub fn key(&self, index: u32, exception_state: &ExceptionState) -> String { + let index_string = NativeValue::new_int64(index.into()); + let key_string = self.context().webf_invoke_module_with_params(&self.module_name, "key", &index_string, exception_state).unwrap(); + key_string.to_string() + } + + pub fn get_all_keys(&self, exception_state: &ExceptionState) -> Vec { + let result = self.context().webf_invoke_module(&self.module_name, "_getAllKeys", exception_state).unwrap(); + let result = result.to_list().iter().map(|item| item.to_string()).collect::>(); + result + } + + pub fn length(&self, exception_state: &ExceptionState) -> i64 { + let length = self.context().webf_invoke_module(&self.module_name, "length", exception_state).unwrap(); + length.to_int64() + } +} diff --git a/bridge/rusty_webf_sys/src/window.rs b/bridge/rusty_webf_sys/src/frame/window.rs similarity index 100% rename from bridge/rusty_webf_sys/src/window.rs rename to bridge/rusty_webf_sys/src/frame/window.rs diff --git a/bridge/rusty_webf_sys/src/html_element.rs b/bridge/rusty_webf_sys/src/html/html_element.rs similarity index 100% rename from bridge/rusty_webf_sys/src/html_element.rs rename to bridge/rusty_webf_sys/src/html/html_element.rs diff --git a/bridge/rusty_webf_sys/src/html/mod.rs b/bridge/rusty_webf_sys/src/html/mod.rs new file mode 100644 index 0000000000..26b1fcaacb --- /dev/null +++ b/bridge/rusty_webf_sys/src/html/mod.rs @@ -0,0 +1,6 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ +pub mod html_element; + +pub use html_element::*; diff --git a/bridge/rusty_webf_sys/src/input/mod.rs b/bridge/rusty_webf_sys/src/input/mod.rs new file mode 100644 index 0000000000..fb13bed837 --- /dev/null +++ b/bridge/rusty_webf_sys/src/input/mod.rs @@ -0,0 +1,6 @@ +/* +* Copyright (C) 2022-present The WebF authors. All rights reserved. +*/ +pub mod touch_init; + +pub use touch_init::*; diff --git a/bridge/rusty_webf_sys/src/touch_init.rs b/bridge/rusty_webf_sys/src/input/touch_init.rs similarity index 100% rename from bridge/rusty_webf_sys/src/touch_init.rs rename to bridge/rusty_webf_sys/src/input/touch_init.rs diff --git a/bridge/rusty_webf_sys/src/lib.rs b/bridge/rusty_webf_sys/src/lib.rs index ca4ac50867..781e5de3d1 100644 --- a/bridge/rusty_webf_sys/src/lib.rs +++ b/bridge/rusty_webf_sys/src/lib.rs @@ -2,103 +2,31 @@ * Copyright (C) 2022-present The WebF authors. All rights reserved. */ #![allow(unused)] -use crate::executing_context::{ExecutingContext, ExecutingContextRustMethods}; -pub mod executing_context; -pub mod document; -pub mod window; -pub mod element; -pub mod document_fragment; -pub mod node; -pub mod event_target; -pub mod event; -pub mod animation_event; -pub mod close_event; -pub mod focus_event; -pub mod gesture_event; -pub mod hashchange_event; -pub mod input_event; -pub mod intersection_change_event; -pub mod mouse_event; -pub mod pointer_event; -pub mod transition_event; -pub mod ui_event; -pub mod container_node; +pub mod dom; +pub mod events; +pub mod frame; +pub mod html; +pub mod input; + pub mod exception_state; -pub mod text; -pub mod comment; -pub mod character_data; -pub mod html_element; +pub mod executing_context; +mod memory_utils; +pub mod native_value; pub mod script_value_ref; -pub mod custom_event; -pub mod add_event_listener_options; -pub mod animation_event_init; -pub mod close_event_init; -pub mod event_init; -pub mod event_listener_options; -pub mod focus_event_init; -pub mod gesture_event_init; -pub mod hashchange_event_init; -pub mod input_event_init; -pub mod intersection_change_event_init; -pub mod keyboard_event_init; -pub mod mouse_event_init; -pub mod pointer_event_init; -pub mod scroll_options; -pub mod scroll_to_options; -pub mod touch_init; -pub mod transition_event_init; -pub mod ui_event_init; pub mod webf_event_listener; pub mod webf_function; -mod memory_utils; -pub use executing_context::*; -pub use document::*; -pub use window::*; -pub use element::*; -pub use document_fragment::*; -pub use node::*; -pub use event_target::*; -pub use event::*; -pub use animation_event::*; -pub use close_event::*; -pub use focus_event::*; -pub use gesture_event::*; -pub use hashchange_event::*; -pub use input_event::*; -pub use intersection_change_event::*; -pub use mouse_event::*; -pub use pointer_event::*; -pub use transition_event::*; -pub use ui_event::*; -pub use container_node::*; +pub use dom::*; +pub use events::*; +pub use frame::*; +pub use html::*; +pub use input::*; + pub use exception_state::*; pub use executing_context::*; -pub use text::*; -pub use comment::*; -pub use character_data::*; -pub use html_element::*; +pub use native_value::*; pub use script_value_ref::*; -pub use custom_event::*; -pub use add_event_listener_options::*; -pub use animation_event_init::*; -pub use close_event_init::*; -pub use event_init::*; -pub use event_listener_options::*; -pub use focus_event_init::*; -pub use gesture_event_init::*; -pub use hashchange_event_init::*; -pub use input_event_init::*; -pub use intersection_change_event_init::*; -pub use keyboard_event_init::*; -pub use mouse_event_init::*; -pub use pointer_event_init::*; -pub use scroll_options::*; -pub use scroll_to_options::*; -pub use touch_init::*; -pub use transition_event_init::*; -pub use ui_event_init::*; pub use webf_event_listener::*; pub use webf_function::*; diff --git a/bridge/rusty_webf_sys/src/memory_utils.rs b/bridge/rusty_webf_sys/src/memory_utils.rs index 22a447eb2d..9e354067d7 100644 --- a/bridge/rusty_webf_sys/src/memory_utils.rs +++ b/bridge/rusty_webf_sys/src/memory_utils.rs @@ -1,21 +1,17 @@ -#[cfg(target_os = "windows")] -use windows::Win32; -use libc; use crate::OpaquePtr; +use libc; +#[cfg(target_os = "windows")] +use windows::Win32::System::Com::CoTaskMemFree; pub fn safe_free_cpp_ptr(ptr: *const T) { unsafe { if cfg!(target_os = "windows") { #[cfg(target_os = "windows")] { - Win32::System::Memory::HeapFree( - Win32::System::Memory::GetProcessHeap().unwrap(), - Win32::System::Memory::HEAP_FLAGS(0), - Option::from(ptr as *const libc::c_void) - ).expect("Failed to call HeapFree"); + CoTaskMemFree(Option::from(ptr as *const libc::c_void)); } } else { libc::free(ptr.cast_mut() as *mut libc::c_void); } } -} \ No newline at end of file +} diff --git a/bridge/rusty_webf_sys/src/native_value.rs b/bridge/rusty_webf_sys/src/native_value.rs new file mode 100644 index 0000000000..dc6bbd2b42 --- /dev/null +++ b/bridge/rusty_webf_sys/src/native_value.rs @@ -0,0 +1,235 @@ +use std::ffi::*; +use std::mem; +#[cfg(target_os = "windows")] +use windows::Win32::System::Com::{CoTaskMemAlloc, CoTaskMemFree}; + +use crate::memory_utils::safe_free_cpp_ptr; + +#[repr(C)] +pub struct SharedNativeString { + pub string_: *mut u16, + pub length_: u32, +} + +#[repr(C)] +pub enum NativeTag { + TagString = 0, + TagInt = 1, + TagBool = 2, + TagNull = 3, + TagFloat64 = 4, + TagJson = 5, + TagList = 6, + TagPointer = 7, + TagFunction = 8, + TagAsyncFunction = 9, + TagUint8Bytes = 10, +} + +#[repr(C)] +#[derive(Copy, Clone)] +pub union ValueField { + pub int64: i64, + pub float64: f64, + pub ptr: *mut c_void, +} + +#[repr(C)] +#[derive(Clone)] +pub struct NativeValue { + pub u: ValueField, + pub uint32: u32, + pub tag: i32, +} + +impl NativeValue { + pub fn new() -> Self { + let size = mem::size_of::(); + + #[cfg(target_os = "windows")] + let ptr = unsafe { CoTaskMemAlloc(size) }; + + #[cfg(not(target_os = "windows"))] + let ptr = unsafe { libc::malloc(size) }; + + let ptr = ptr as *mut NativeValue; + let value = unsafe { ptr.read() }; + value + } + + fn create_string_ptr(val: &str, len: usize) -> *mut SharedNativeString { + let size = len * mem::size_of::(); + + #[cfg(target_os = "windows")] + let ptr = unsafe { CoTaskMemAlloc(size) }; + + #[cfg(not(target_os = "windows"))] + let ptr = unsafe { libc::malloc(size) }; + + let ptr = ptr as *mut u16; + + for (i, c) in val.encode_utf16().enumerate() { + unsafe { + ptr.add(i).write(c); + } + } + + let mut shared_string = SharedNativeString { + string_: ptr, + length_: len as u32, + }; + + let shared_string_size = mem::size_of::(); + + #[cfg(target_os = "windows")] + let shared_string_ptr = unsafe { CoTaskMemAlloc(shared_string_size) }; + + #[cfg(not(target_os = "windows"))] + let shared_string_ptr = unsafe { libc::malloc(shared_string_size) }; + + let shared_string_ptr = shared_string_ptr as *mut SharedNativeString; + unsafe { + shared_string_ptr.write(shared_string); + } + + shared_string_ptr + } + + pub fn new_string(val: &str) -> Self { + let len = val.len(); + let shared_string_ptr = Self::create_string_ptr(val, len); + let mut value = Self::new(); + value.tag = NativeTag::TagString as i32; + value.u.ptr = shared_string_ptr as *mut c_void; + value.uint32 = len as u32; + value + } + + pub fn is_string(&self) -> bool { + self.tag == NativeTag::TagString as i32 + } + + pub fn to_string(&self) -> String { + let ptr = unsafe { + self.u.ptr as *mut SharedNativeString + }; + let string_struct = unsafe { ptr.read() }; + let slice = unsafe { std::slice::from_raw_parts(string_struct.string_, string_struct.length_.try_into().unwrap()) }; + String::from_utf16_lossy(slice) + } + + pub fn new_null() -> Self { + let mut value = Self::new(); + value.tag = NativeTag::TagNull as i32; + value.u.int64 = 0; + value.uint32 = 0; + value + } + + pub fn is_null(&self) -> bool { + self.tag == NativeTag::TagNull as i32 + } + + pub fn new_float64(val: f64) -> Self { + let mut value = Self::new(); + value.tag = NativeTag::TagFloat64 as i32; + value.u.float64 = val; + value.uint32 = 0; + value + } + + pub fn is_float64(&self) -> bool { + self.tag == NativeTag::TagFloat64 as i32 + } + + pub fn to_float64(&self) -> f64 { + unsafe { + self.u.float64 + } + } + + pub fn new_bool(val: bool) -> Self { + let mut value = Self::new(); + value.tag = NativeTag::TagBool as i32; + value.u.int64 = if val { 1 } else { 0 }; + value.uint32 = 0; + value + } + + pub fn is_bool(&self) -> bool { + self.tag == NativeTag::TagBool as i32 + } + + pub fn to_bool(&self) -> bool { + unsafe { + self.u.int64 != 0 + } + } + + pub fn new_int64(val: i64) -> Self { + let mut value = Self::new(); + value.tag = NativeTag::TagInt as i32; + value.u.int64 = val; + value.uint32 = 0; + value + } + + pub fn is_int64(&self) -> bool { + self.tag == NativeTag::TagInt as i32 + } + + pub fn to_int64(&self) -> i64 { + unsafe { + self.u.int64 + } + } + + pub fn new_list(values: Vec) -> Self { + let size = values.len(); + let array_size = size * mem::size_of::(); + + #[cfg(target_os = "windows")] + let array_ptr = unsafe { CoTaskMemAlloc(array_size) }; + + #[cfg(not(target_os = "windows"))] + let array_ptr = unsafe { libc::malloc(array_size) }; + + let array_ptr = array_ptr as *mut NativeValue; + + for (i, val) in values.iter().enumerate() { + let mut value = val.clone(); + unsafe { + array_ptr.add(i).write(value); + } + } + + let mut value = Self::new(); + value.tag = NativeTag::TagList as i32; + value.u.ptr = array_ptr as *mut c_void; + value.uint32 = size as u32; + value + } + + pub fn is_list(&self) -> bool { + self.tag == NativeTag::TagList as i32 + } + + pub fn to_list(&self) -> Vec { + let mut values = Vec::new(); + let ptr = unsafe { + self.u.ptr as *mut NativeValue + }; + for i in 0..self.uint32 { + let offset = i.try_into().unwrap(); + let val = unsafe { ptr.add(offset).read() }; + values.push(val); + } + values + } +} + +impl Drop for NativeValue { + fn drop(&mut self) { + // no need to drop inner structure, it will be freed by the dart side + } +} diff --git a/bridge/rusty_webf_sys/src/webf_function.rs b/bridge/rusty_webf_sys/src/webf_function.rs index be8ea330aa..e39af4ee0d 100644 --- a/bridge/rusty_webf_sys/src/webf_function.rs +++ b/bridge/rusty_webf_sys/src/webf_function.rs @@ -4,7 +4,7 @@ use std::ffi::*; use crate::*; -pub type WebFNativeFunction = Box; +pub type WebFNativeFunction = Box NativeValue>; pub struct WebFNativeFunctionContextData { pub func: WebFNativeFunction, @@ -20,8 +20,8 @@ impl Drop for WebFNativeFunctionContextData { pub struct WebFNativeFunctionContext { pub callback: extern "C" fn(callback_context: *const OpaquePtr, argc: c_int, - argv: *const OpaquePtr, - exception_state: *const OpaquePtr) -> *const c_void, + argv: *const NativeValue, + exception_state: *const OpaquePtr) -> NativeValue, pub free_ptr: extern "C" fn(callback_context: *const OpaquePtr) -> *const c_void, pub ptr: *const WebFNativeFunctionContextData, } @@ -29,9 +29,9 @@ pub struct WebFNativeFunctionContext { pub extern "C" fn invoke_webf_native_function( callback_context_ptr: *const OpaquePtr, argc: c_int, - argv: *const OpaquePtr, + argv: *const NativeValue, exception_state: *const OpaquePtr, -) -> *const c_void { +) -> NativeValue { let callback_context = unsafe { &(*(callback_context_ptr as *mut WebFNativeFunctionContext)) }; @@ -41,10 +41,8 @@ pub extern "C" fn invoke_webf_native_function( unsafe { let func = &(*callback_context_data).func; - func(argc, argv); + func(argc, argv) } - - std::ptr::null() } pub extern "C" fn release_webf_native_function(callback_context_ptr: *const OpaquePtr) -> *const c_void { diff --git a/bridge/scripts/code_generator/bin/code_generator.js b/bridge/scripts/code_generator/bin/code_generator.js index 13a4198132..c7535f0a85 100644 --- a/bridge/scripts/code_generator/bin/code_generator.js +++ b/bridge/scripts/code_generator/bin/code_generator.js @@ -277,12 +277,15 @@ function genRustCodeFromTypeDefine() { for (let i = 0; i < blobs.length; i ++) { let b = blobs[i]; let result = generateRustSource(b); + const folders = b.source.replace(source, '').replace(b.filename + '.d.ts', '').split(path.sep) + .filter(f => f !== '').join(path.sep); + const rsDist = path.join(b.dist, '../rusty_webf_sys/src', folders); - if (!fs.existsSync(b.dist)) { - fs.mkdirSync(b.dist, {recursive: true}); + if (!fs.existsSync(rsDist)) { + fs.mkdirSync(rsDist, {recursive: true}); } - let genFilePath = path.join(b.dist, '../rusty_webf_sys/src', b.filename); + let genFilePath = path.join(rsDist, b.filename); wirteFileIfChanged(genFilePath + '.rs', result); } diff --git a/webf/example/rust_builder/rust/src/lib.rs b/webf/example/rust_builder/rust/src/lib.rs index 5fd63f752d..95a96dfce7 100644 --- a/webf/example/rust_builder/rust/src/lib.rs +++ b/webf/example/rust_builder/rust/src/lib.rs @@ -1,7 +1,7 @@ use std::ffi::{c_void, CString}; use webf_sys::event::Event; use webf_sys::executing_context::ExecutingContextRustMethods; -use webf_sys::{element, initialize_webf_api, AddEventListenerOptions, EventMethods, EventTargetMethods, RustValue}; +use webf_sys::{async_storage, element, initialize_webf_api, navigator, AddEventListenerOptions, EventMethods, EventTargetMethods, NativeValue, RustValue}; use webf_sys::element::Element; use webf_sys::node::NodeMethods; @@ -11,12 +11,66 @@ pub extern "C" fn init_webf_app(handle: RustValue) println!("Context created"); let exception_state = context.create_exception_state(); let document = context.document(); + let navigator = context.navigator(); + + let ua_string = navigator.user_agent(&exception_state); + println!("User Agent: {}", ua_string); + + let local_storage = context.local_storage(); + + let result = local_storage.set_item("test", "test2", &exception_state); + + match result { + Ok(_) => { + println!("Local Storage Set Item Success"); + }, + Err(err) => { + println!("Local Storage Set Item Failed: {:?}", err); + } + } + + println!("Local Storage value for \"a\": {:?}", local_storage.get_item("a", &exception_state)); + println!("Local Storage Keys: {:?}", local_storage.get_all_keys(&exception_state)); + println!("Local Storage Length: {:?}", local_storage.length(&exception_state)); + println!("Local Storage value for \"test\": {:?}", local_storage.get_item("test", &exception_state)); + + local_storage.clear(&exception_state); + + let async_storage_1 = context.async_storage(); + + let async_storage_set_item_callback = Box::new(|value: Result, String>| { + match value { + Ok(value) => { + println!("Async Storage Set Item Success: {:?}", value); + }, + Err(err) => { + println!("Async Storage Set Item Failed: {:?}", err); + } + } + }); + + async_storage_1.set_item("a", "b", async_storage_set_item_callback, &exception_state); + + let async_storage_2 = context.async_storage(); + + let async_storage_get_item_callback = Box::new(|value: Result, String>| { + match value { + Ok(value) => { + println!("Async Storage Get Item Success: {:?}", value); + }, + Err(err) => { + println!("Async Storage Get Item Failed: {:?}", err); + } + } + }); + + async_storage_2.get_item("a", async_storage_get_item_callback, &exception_state); let timer_callback = Box::new(move || { println!("Timer Callback"); }); - context.set_interval_with_callback_and_timeout(timer_callback, 1000, &exception_state).unwrap(); + context.set_timeout_with_callback_and_timeout(timer_callback, 1000, &exception_state).unwrap(); let click_event = document.create_event("custom_click", &exception_state).unwrap(); document.dispatch_event(&click_event, &exception_state);