Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

[WIP]feat: preloading #544

Closed
wants to merge 17 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 37 additions & 2 deletions bridge/core/api/api.cc
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,23 @@ void evaluateQuickjsByteCodeInternal(void* page_,
persistent_handle, result_callback, is_success);
}

void parseHTMLInternal(void* page_, const char* code, int32_t length) {
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 parseHTMLInternal(void* page_,
char* code,
int32_t length,
Dart_PersistentHandle dart_handle,
ParseHTMLCallback result_callback) {
auto page = reinterpret_cast<webf::WebFPage*>(page_);
assert(std::this_thread::get_id() == page->currentThread());
page->parseHTML(code, length);
delete code;
dart_free(code);
page->dartIsolateContext()->dispatcher()->PostToDart(page->isDedicated(), ReturnParseHTMLToDart, dart_handle,
result_callback);
}

static void ReturnInvokeEventResultToDart(Dart_Handle persistent_handle,
Expand All @@ -85,4 +97,27 @@ void invokeModuleEventInternal(void* page_,
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 dumpQuickJsByteCodeInternal(void* page_,
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<webf::WebFPage*>(page_);
auto dart_isolate_context = page->executingContext()->dartIsolateContext();
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->dispatcher()->PostToDart(page->isDedicated(), ReturnDumpByteCodeResultToDart, persistent_handle,
result_callback);
}

} // namespace webf
15 changes: 14 additions & 1 deletion bridge/core/api/api.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,11 @@ void evaluateQuickjsByteCodeInternal(void* page_,
int32_t byteLen,
Dart_PersistentHandle persistent_handle,
EvaluateQuickjsByteCodeCallback result_callback);
void parseHTMLInternal(void* page_, const char* code, int32_t length);
void parseHTMLInternal(void* page_,
char* code,
int32_t length,
Dart_PersistentHandle dart_handle,
ParseHTMLCallback result_callback);

void invokeModuleEventInternal(void* page_,
void* module_name,
Expand All @@ -35,6 +39,15 @@ void invokeModuleEventInternal(void* page_,
Dart_Handle dart_handle,
InvokeModuleEventCallback result_callback);

void dumpQuickJsByteCodeInternal(void* page_,
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);

} // namespace webf

#endif // WEBF_CORE_API_API_H_
6 changes: 4 additions & 2 deletions bridge/core/executing_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -337,13 +337,15 @@ ExecutionContextData* ExecutingContext::contextData() {
uint8_t* ExecutingContext::DumpByteCode(const char* code,
uint32_t codeLength,
const char* sourceURL,
size_t* bytecodeLength) {
uint64_t* bytecodeLength) {
JSValue object =
JS_Eval(script_state_.ctx(), code, codeLength, sourceURL, JS_EVAL_TYPE_GLOBAL | JS_EVAL_FLAG_COMPILE_ONLY);
bool success = HandleException(&object);
if (!success)
return nullptr;
uint8_t* bytes = JS_WriteObject(script_state_.ctx(), bytecodeLength, object, JS_WRITE_OBJ_BYTECODE);
size_t len;
uint8_t* bytes = JS_WriteObject(script_state_.ctx(), &len, object, JS_WRITE_OBJ_BYTECODE);
*bytecodeLength = len;
JS_FreeValue(script_state_.ctx(), object);
return bytes;
}
Expand Down
2 changes: 1 addition & 1 deletion bridge/core/executing_context.h
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ class ExecutingContext {
void EnqueueMicrotask(MicrotaskCallback callback, void* data = nullptr);
void DefineGlobalProperty(const char* prop, JSValueConst value);
ExecutionContextData* contextData();
uint8_t* DumpByteCode(const char* code, uint32_t codeLength, const char* sourceURL, size_t* bytecodeLength);
uint8_t* DumpByteCode(const char* code, uint32_t codeLength, const char* sourceURL, uint64_t* bytecodeLength);

// Make global object inherit from WindowProperties.
void InstallGlobal();
Expand Down
2 changes: 1 addition & 1 deletion bridge/core/executing_context_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -334,7 +334,7 @@ TEST(Context, evaluateByteCode) {
auto errorHandler = [](double contextId, const char* errmsg) { errorHandlerExecuted = true; };
auto env = TEST_init(errorHandler);
const char* code = "function f() { console.log(arguments)} f(1,2,3,4);";
size_t byteLen;
uint64_t byteLen;
uint8_t* bytes = env->page()->dumpByteCode(code, strlen(code), "vm://", &byteLen);
env->page()->evaluateByteCode(bytes, byteLen);

Expand Down
5 changes: 4 additions & 1 deletion bridge/core/html/parser/html_parser.cc
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,10 @@ void HTMLParser::traverseHTML(Node* root_node, GumboNode* node) {
bool HTMLParser::parseHTML(const std::string& html, Node* root_node, bool isHTMLFragment) {
if (root_node != nullptr) {
if (auto* root_container_node = DynamicTo<ContainerNode>(root_node)) {
root_container_node->RemoveChildren();
{
MemberMutationScope scope{root_node->GetExecutingContext()};
root_container_node->RemoveChildren();
}

if (!trim(html).empty()) {
GumboOutput* htmlTree = parse(html, isHTMLFragment);
Expand Down
2 changes: 1 addition & 1 deletion bridge/core/page.cc
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ void WebFPage::evaluateScript(const char* script, size_t length, const char* url
context_->EvaluateJavaScript(script, length, url, startLine);
}

uint8_t* WebFPage::dumpByteCode(const char* script, size_t length, const char* url, size_t* byteLength) {
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, length, url, byteLength);
Expand Down
2 changes: 1 addition & 1 deletion bridge/core/page.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class WebFPage final {
int startLine);
bool parseHTML(const char* code, size_t length);
void evaluateScript(const char* script, size_t length, const char* url, int startLine);
uint8_t* dumpByteCode(const char* script, size_t length, const char* url, size_t* byteLength);
uint8_t* dumpByteCode(const char* script, size_t length, const char* url, uint64_t* byteLength);
bool evaluateByteCode(uint8_t* bytes, size_t byteLength);

std::thread::id currentThread() const;
Expand Down
1 change: 1 addition & 0 deletions bridge/core/script_state.cc
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ JSRuntime* ScriptState::runtime() {
ScriptState::~ScriptState() {
ctx_invalid_ = true;
JSRuntime* rt = JS_GetRuntime(ctx_);
JS_TurnOnGC(rt);
JS_FreeContext(ctx_);

// Run GC to clean up remaining objects about m_ctx;
Expand Down
15 changes: 14 additions & 1 deletion bridge/include/webf_bridge.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ typedef void (*AllocateNewPageCallback)(Dart_Handle dart_handle, void*);
typedef void (*DisposePageCallback)(Dart_Handle dart_handle);
typedef void (*InvokeModuleEventCallback)(Dart_Handle dart_handle, void*);
typedef void (*EvaluateQuickjsByteCodeCallback)(Dart_Handle dart_handle, int8_t);
typedef void (*DumpQuickjsByteCodeCallback)(Dart_Handle);
typedef void (*ParseHTMLCallback)(Dart_Handle);
typedef void (*EvaluateScriptsCallback)(Dart_Handle dart_handle, int8_t);

WEBF_EXPORT_C
Expand Down Expand Up @@ -79,8 +81,19 @@ void evaluateQuickjsByteCode(void* page,
int32_t byteLen,
Dart_Handle dart_handle,
EvaluateQuickjsByteCodeCallback result_callback);

WEBF_EXPORT_C
void dumpQuickjsByteCode(void* page,
const char* code,
int32_t code_len,
uint8_t** parsed_bytecodes,
uint64_t* bytecode_len,
const char* url,
Dart_Handle dart_handle,
DumpQuickjsByteCodeCallback result_callback);

WEBF_EXPORT_C
void parseHTML(void* page, const char* code, int32_t length);
void parseHTML(void* page, char* code, int32_t length, Dart_Handle dart_handle, ParseHTMLCallback result_callback);
WEBF_EXPORT_C
void* parseSVGResult(const char* code, int32_t length);
WEBF_EXPORT_C
Expand Down
27 changes: 24 additions & 3 deletions bridge/webf_bridge.cc
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,25 @@ void evaluateScripts(void* page_,
bytecode_len, bundleFilename, startLine, persistent_handle, result_callback);
}

void dumpQuickjsByteCode(void* page_,
const char* code,
int32_t code_len,
uint8_t** parsed_bytecodes,
uint64_t* bytecode_len,
const char* url,
Dart_Handle dart_handle,
DumpQuickjsByteCodeCallback result_callback) {
#if ENABLE_LOG
WEBF_LOG(VERBOSE) << "[Dart] dumpQuickjsByteCode call" << std::endl;
#endif

auto page = reinterpret_cast<webf::WebFPage*>(page_);
Dart_PersistentHandle persistent_handle = Dart_NewPersistentHandle_DL(dart_handle);
page->dartIsolateContext()->dispatcher()->PostToJs(
page->isDedicated(), page->contextId(), webf::dumpQuickJsByteCodeInternal, page, code, code_len, parsed_bytecodes,
bytecode_len, url, persistent_handle, result_callback);
}

void evaluateQuickjsByteCode(void* page_,
uint8_t* bytes,
int32_t byteLen,
Expand All @@ -154,13 +173,15 @@ void evaluateQuickjsByteCode(void* page_,
persistent_handle, result_callback);
}

void parseHTML(void* page_, const char* code, int32_t length) {
void parseHTML(void* page_, char* code, int32_t length, Dart_Handle dart_handle, ParseHTMLCallback result_callback) {
#if ENABLE_LOG
WEBF_LOG(VERBOSE) << "[Dart] parseHTMLWrapper call" << std::endl;
#endif
auto page = reinterpret_cast<webf::WebFPage*>(page_);
Dart_PersistentHandle persistent_handle = Dart_NewPersistentHandle_DL(dart_handle);
page->executingContext()->dartIsolateContext()->dispatcher()->PostToJs(page->isDedicated(), page->contextId(),
webf::parseHTMLInternal, page_, code, length);
webf::parseHTMLInternal, page_, code, length,
persistent_handle, result_callback);
}

void registerPluginByteCode(uint8_t* bytes, int32_t length, const char* pluginName) {
Expand Down Expand Up @@ -281,4 +302,4 @@ void executeNativeCallback(DartWork* work_ptr) {
auto dart_work = *(work_ptr);
dart_work(false);
delete work_ptr;
}
}
2 changes: 1 addition & 1 deletion integration_tests/macos/Runner.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@
isa = PBXProject;
attributes = {
LastSwiftUpdateCheck = 0920;
LastUpgradeCheck = 1430;
LastUpgradeCheck = 1300;
ORGANIZATIONNAME = "";
TargetAttributes = {
33CC10EC2044A3C60003C045 = {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1430"
LastUpgradeVersion = "1300"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
Expand Down
97 changes: 51 additions & 46 deletions webf/example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,58 @@ class MyApp extends StatelessWidget {
title: 'Kraken Browser',
// theme: ThemeData.dark(),
debugShowCheckedModeBanner: false,
home: MyBrowser(),
home: FirstPage(title: 'Landing Bay'),
);
}
}

class FirstPage extends StatefulWidget {
const FirstPage({Key? key, required this.title}) : super(key: key);
final String title;

@override
State<StatefulWidget> createState() {
return FirstPageState();
}
}

class FirstPageState extends State<FirstPage> {
late WebFController controller;

@override
void didChangeDependencies() {
super.didChangeDependencies();
controller = WebFController(
context,
devToolsService: ChromeDevToolsService(),
);
controller.preRendering(WebFBundle.fromUrl('assets:assets/bundle.html'));
}

@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Center(
child: ElevatedButton(
onPressed: () {
Navigator.push(context, MaterialPageRoute(builder: (context) {
return MyBrowser(title: 'SecondPage', controller: controller);
}));
},
child: const Text('Open WebF Page'),
),
),
);
}
}

class MyBrowser extends StatefulWidget {
MyBrowser({Key? key, this.title}) : super(key: key);
MyBrowser({Key? key, this.title, required this.controller}) : super(key: key);

final WebFController controller;

// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
Expand All @@ -52,54 +97,14 @@ class _MyHomePageState extends State<MyBrowser> {

@override
Widget build(BuildContext context) {
final MediaQueryData queryData = MediaQuery.of(context);
final TextEditingController textEditingController = TextEditingController();

WebF? _kraken;
AppBar appBar = AppBar(
backgroundColor: Colors.black87,
titleSpacing: 10.0,
title: Container(
height: 40.0,
child: TextField(
controller: textEditingController,
onSubmitted: (value) {
textEditingController.text = value;
_kraken?.load(WebFBundle.fromUrl(value));
},
decoration: InputDecoration(
hintText: 'Enter URL',
hintStyle: TextStyle(color: Colors.black54, fontSize: 16.0),
contentPadding: const EdgeInsets.all(10.0),
filled: true,
fillColor: Colors.grey,
border: outlineBorder,
focusedBorder: outlineBorder,
enabledBorder: outlineBorder,
),
style: TextStyle(color: Colors.black, fontSize: 16.0),
),
),
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
);

final Size viewportSize = queryData.size;
return Scaffold(
appBar: appBar,
appBar: AppBar(
title: Text('WebF Demo'),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
children: [
_kraken = WebF(
devToolsService: ChromeDevToolsService(),
viewportWidth: viewportSize.width - queryData.padding.horizontal,
viewportHeight: viewportSize.height - appBar.preferredSize.height - queryData.padding.vertical,
bundle: WebFBundle.fromUrl('assets:assets/bundle.html'),
),
],
),
child: WebF(controller: widget.controller),
));
}
}
Loading
Loading