Skip to content

Commit

Permalink
fix: fix integration test and timer.
Browse files Browse the repository at this point in the history
  • Loading branch information
andycall committed May 25, 2022
1 parent cb6f1c0 commit 9701560
Show file tree
Hide file tree
Showing 21 changed files with 131 additions and 32 deletions.
2 changes: 2 additions & 0 deletions bridge/bindings/qjs/binding_initializer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
#include "qjs_text.h"
#include "qjs_screen.h"
#include "qjs_window.h"
#include "qjs_blob.h"
#include "qjs_window_or_worker_global_scope.h"

namespace kraken {
Expand Down Expand Up @@ -65,6 +66,7 @@ void InstallBindings(ExecutingContext* context) {
QJSCSSStyleDeclaration::Install(context);
QJSBoundingClientRect::Install(context);
QJSScreen::Install(context);
QJSBlob::Install(context);

// Legacy bindings, not standard.
QJSElementAttributes::Install(context);
Expand Down
2 changes: 1 addition & 1 deletion bridge/bindings/qjs/script_promise.cc
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ ScriptPromise::ScriptPromise(JSContext* ctx, JSValue promise) : ctx_(ctx) {
}

JSValue ScriptPromise::ToQuickJS() {
return JS_NULL;
return JS_DupValue(ctx_, promise_.QJSValue());
}

void ScriptPromise::Trace(GCVisitor* visitor) {}
Expand Down
10 changes: 8 additions & 2 deletions bridge/bindings/qjs/script_promise_resolver.cc
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@

namespace kraken {

ScriptPromiseResolver* ScriptPromiseResolver::Create(ExecutingContext* context) {
return new ScriptPromiseResolver(context);
std::shared_ptr<ScriptPromiseResolver> ScriptPromiseResolver::Create(ExecutingContext* context) {
return std::make_shared<ScriptPromiseResolver>(context);
}

ScriptPromiseResolver::ScriptPromiseResolver(ExecutingContext* context) : context_(context) {
Expand All @@ -22,6 +22,12 @@ ScriptPromiseResolver::ScriptPromiseResolver(ExecutingContext* context) : contex
context->GetPendingPromises()->TrackPendingPromises(ScriptPromise(context_->ctx(), promise_));
}

ScriptPromiseResolver::~ScriptPromiseResolver() {
JS_FreeValue(context_->ctx(), promise_);
JS_FreeValue(context_->ctx(), resolve_func_);
JS_FreeValue(context_->ctx(), reject_func_);
}

ScriptPromise ScriptPromiseResolver::Promise() {
return ScriptPromise(context_->ctx(), promise_);
}
Expand Down
7 changes: 5 additions & 2 deletions bridge/bindings/qjs/script_promise_resolver.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ namespace kraken {

class ScriptPromiseResolver {
public:
static ScriptPromiseResolver* Create(ExecutingContext* context);
static std::shared_ptr<ScriptPromiseResolver> Create(ExecutingContext* context);
ScriptPromiseResolver() = delete;
ScriptPromiseResolver(ExecutingContext* context);
~ScriptPromiseResolver();

// Return a promise object and wait to be resolve or reject.
// Note that an empty ScriptPromise will be returned after resolve or
Expand Down Expand Up @@ -51,7 +52,9 @@ class ScriptPromiseResolver {
return;
assert(new_state == kResolving || new_state == kRejecting);
state_ = new_state;
ResolveOrRejectImmediately(toQuickJS(context_->ctx(), value));
JSValue qjs_value = toQuickJS(context_->ctx(), value);
ResolveOrRejectImmediately(qjs_value);
JS_FreeValue(context_->ctx(), qjs_value);
}

void ResolveOrRejectImmediately(JSValue value);
Expand Down
4 changes: 4 additions & 0 deletions bridge/core/css/legacy/css_style_declaration.cc
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ AtomicString CSSStyleDeclaration::InternalGetPropertyValue(std::string& name) {
bool CSSStyleDeclaration::InternalSetProperty(std::string& name, const AtomicString& value) {
name = parseJavaScriptCSSPropertyName(name);

if (properties_[name] == value) {
return true;
}

properties_[name] = value;

std::unique_ptr<NativeString> args_01 = stringToNativeString(name);
Expand Down
27 changes: 27 additions & 0 deletions bridge/core/css/legacy/css_style_declaration_test.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
/*
* Copyright (C) 2021 Alibaba Inc. All rights reserved.
* Author: Kraken Team.
*/

#include "gtest/gtest.h"
#include "kraken_test_env.h"

using namespace kraken;

TEST(CSSStyleDeclaration, setStyleData) {
bool static errorCalled = false;
bool static logCalled = false;
kraken::KrakenPage::consoleMessageHandler = [](void* ctx, const std::string& message, int logLevel) {
logCalled = true;
};
auto bridge = TEST_init([](int32_t contextId, const char* errmsg) {
KRAKEN_LOG(VERBOSE) << errmsg;
errorCalled = true;
});
auto context = bridge->GetExecutingContext();
const char* code =
"document.documentElement.style.backgroundColor = 'white';"
"document.documentElement.style.backgroundColor = 'white';";
bridge->evaluateScript(code, strlen(code), "vm://", 0);
EXPECT_EQ(errorCalled, false);
}
12 changes: 8 additions & 4 deletions bridge/core/dom/element.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
*/

#include "element.h"

#include <utility>
#include "binding_call_methods.h"
#include "bindings/qjs/exception_state.h"
#include "bindings/qjs/script_promise.h"
Expand Down Expand Up @@ -215,9 +217,9 @@ class ElementSnapshotReader {
public:
ElementSnapshotReader(ExecutingContext* context,
Element* element,
ScriptPromiseResolver* resolver,
std::shared_ptr<ScriptPromiseResolver> resolver,
double device_pixel_ratio)
: context_(context), element_(element), resolver_(resolver), device_pixel_ratio_(device_pixel_ratio) {
: context_(context), element_(element), resolver_(std::move(resolver)), device_pixel_ratio_(device_pixel_ratio) {
Start();
};

Expand All @@ -228,7 +230,7 @@ class ElementSnapshotReader {
private:
ExecutingContext* context_;
Element* element_;
ScriptPromiseResolver* resolver_;
std::shared_ptr<ScriptPromiseResolver> resolver_;
double device_pixel_ratio_;
};

Expand All @@ -250,12 +252,14 @@ void ElementSnapshotReader::Start() {
}

void ElementSnapshotReader::HandleSnapshot(uint8_t* bytes, int32_t length) {
MemberMutationScope mutation_scope{context_};
Blob* blob = Blob::Create(context_);
blob->AppendBytes(bytes, length);
resolver_->Resolve<Blob*>(blob);
}

void ElementSnapshotReader::HandleFailed(const char* error) {
MemberMutationScope mutation_scope{context_};
ExceptionState exception_state;
exception_state.ThrowException(context_->ctx(), ErrorType::InternalError, error);
resolver_->Reject(exception_state);
Expand All @@ -266,7 +270,7 @@ ScriptPromise Element::toBlob(ExceptionState& exception_state) {
}

ScriptPromise Element::toBlob(double device_pixel_ratio, ExceptionState& exception_state) {
auto* resolver = ScriptPromiseResolver::Create(GetExecutingContext());
auto resolver = ScriptPromiseResolver::Create(GetExecutingContext());
new ElementSnapshotReader(GetExecutingContext(), this, resolver, device_pixel_ratio);
return resolver->Promise();
}
Expand Down
1 change: 1 addition & 0 deletions bridge/core/dom/node.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ interface Node extends EventTarget {
isEqualNode(otherNode: Node | null): boolean;
isSameNode(otherNode: Node | null): boolean;
removeChild(oldChild: Node): Node;
remove(): void;
replaceChild(newChild: Node, oldChild: Node): Node;

new(): void;
Expand Down
10 changes: 5 additions & 5 deletions bridge/core/fileapi/blob.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ class BlobReaderClient {
public:
enum ReadType { kReadAsText, kReadAsArrayBuffer };

BlobReaderClient(ExecutingContext* context, Blob* blob, ScriptPromiseResolver* resolver, ReadType read_type)
: context_(context), blob_(blob), resolver_(resolver), read_type_(read_type) {
BlobReaderClient(ExecutingContext* context, Blob* blob, std::shared_ptr<ScriptPromiseResolver> resolver, ReadType read_type)
: context_(context), blob_(blob), resolver_(std::move(resolver)), read_type_(read_type) {
Start();
};

Expand All @@ -26,7 +26,7 @@ class BlobReaderClient {
private:
ExecutingContext* context_;
Blob* blob_;
ScriptPromiseResolver* resolver_;
std::shared_ptr<ScriptPromiseResolver> resolver_;
ReadType read_type_;
};

Expand Down Expand Up @@ -113,13 +113,13 @@ std::string Blob::type() {
}

ScriptPromise Blob::arrayBuffer(ExceptionState& exception_state) {
auto* resolver = ScriptPromiseResolver::Create(GetExecutingContext());
auto resolver = ScriptPromiseResolver::Create(GetExecutingContext());
new BlobReaderClient(GetExecutingContext(), this, resolver, BlobReaderClient::ReadType::kReadAsArrayBuffer);
return resolver->Promise();
}

ScriptPromise Blob::text(ExceptionState& exception_state) {
auto* resolver = ScriptPromiseResolver::Create(GetExecutingContext());
auto resolver = ScriptPromiseResolver::Create(GetExecutingContext());
new BlobReaderClient(GetExecutingContext(), this, resolver, BlobReaderClient::ReadType::kReadAsText);
return resolver->Promise();
}
Expand Down
6 changes: 4 additions & 2 deletions bridge/core/frame/dom_timer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
*/

#include "dom_timer.h"

#include <utility>
#include "bindings/qjs/cppgc/garbage_collected.h"
#include "bindings/qjs/qjs_engine_patch.h"
#include "core/executing_context.h"
Expand All @@ -14,12 +16,12 @@

namespace kraken {

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

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

void DOMTimer::Fire() {
if (!callback_->IsFunction(context_->ctx()))
Expand Down
16 changes: 14 additions & 2 deletions bridge/core/frame/dom_timer.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,21 +14,33 @@ namespace kraken {

class DOMTimer {
public:
static std::shared_ptr<DOMTimer> create(ExecutingContext* context, std::shared_ptr<QJSFunction> callback);
enum TimerStatus {
kPending,
kExecuting,
kFinished
};

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

// Trigger timer callback.
void Fire();

int32_t timerId() const { return timerId_; };
[[nodiscard]] int32_t timerId() const { return timerId_; };
void setTimerId(int32_t timerId);

void SetStatus(TimerStatus status) {
status_ = status;
}
[[nodiscard]] TimerStatus status() const { return status_; }

ExecutingContext* context() { return context_; }

private:
ExecutingContext* context_{nullptr};
int32_t timerId_{-1};
int32_t isInterval_{false};
TimerStatus status_;
std::shared_ptr<QJSFunction> callback_;
};

Expand Down
5 changes: 4 additions & 1 deletion bridge/core/frame/dom_timer_coordinator.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,10 @@ void* DOMTimerCoordinator::removeTimeoutById(int32_t timerId) {
return nullptr;
auto timer = m_activeTimers[timerId];

m_activeTimers.erase(timerId);
if (timer->status() == DOMTimer::kPending) {
m_activeTimers.erase(timerId);
}

return nullptr;
}

Expand Down
22 changes: 21 additions & 1 deletion bridge/core/frame/dom_timer_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,11 @@ console.log('1234');

TEST(Timer, clearTimeout) {
auto bridge = TEST_init();
static bool log_called = false;

kraken::KrakenPage::consoleMessageHandler = [](void* ctx, const std::string& message, int logLevel) {};
kraken::KrakenPage::consoleMessageHandler = [](void* ctx, const std::string& message, int logLevel) {
log_called = true;
};

std::string code = R"(
function getCachedData() {
Expand All @@ -58,6 +61,23 @@ let timer = setTimeout(async () => {
console.log(data);
}, 10);
clearTimeout(timer);
)";

bridge->evaluateScript(code.c_str(), code.size(), "vm://", 0);
TEST_runLoop(bridge->GetExecutingContext());

EXPECT_EQ(log_called, false);
}

TEST(Timer, clearTimeoutWhenSetTimeout) {
auto bridge = TEST_init();

kraken::KrakenPage::consoleMessageHandler = [](void* ctx, const std::string& message, int logLevel) {};

std::string code = R"(
let timer = setTimeout(() => {
clearTimeout(timer);
}, 10);
)";

bridge->evaluateScript(code.c_str(), code.size(), "vm://", 0);
Expand Down
2 changes: 2 additions & 0 deletions bridge/core/frame/window_or_worker_global_scope.cc
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,9 @@ static void handleTransientCallback(void* ptr, int32_t contextId, const char* er
if (!context->IsValid())
return;

timer->SetStatus(DOMTimer::TimerStatus::kExecuting);
handleTimerCallback(timer, errmsg);
timer->SetStatus(DOMTimer::TimerStatus::kFinished);

context->Timers()->removeTimeoutById(timer->timerId());
}
Expand Down
7 changes: 4 additions & 3 deletions bridge/polyfill/src/test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,9 +135,10 @@ global.simulateInputText = __kraken_simulate_inputtext__;

function resetDocumentElement() {
window.scrollTo(0, 0);
document.removeChild(document.documentElement);
let html = document.createElement('html');
document.appendChild(html);

while(document.documentElement.firstChild) {
document.documentElement.firstChild.remove();
}

let head = document.createElement('head');
document.documentElement.appendChild(head);
Expand Down
2 changes: 0 additions & 2 deletions bridge/test/kraken_test_context.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,6 @@ static JSValue matchImageSnapshot(JSContext* ctx, JSValueConst this_val, int arg
}

std::unique_ptr<NativeString> screenShotNativeString = kraken::jsValueToNativeString(ctx, screenShotValue);
auto bridge = static_cast<KrakenTestContext*>(static_cast<KrakenPage*>(context->owner())->owner);
auto* callbackContext = new ImageSnapShotContext{JS_DupValue(ctx, callbackValue), context};

auto fn = [](void* ptr, int32_t contextId, int8_t result, const char* errmsg) {
Expand All @@ -89,7 +88,6 @@ static JSValue matchImageSnapshot(JSContext* ctx, JSValueConst this_val, int arg

callbackContext->context->DrainPendingPromiseJobs();
JS_FreeValue(callbackContext->context->ctx(), callbackContext->callback);
list_del(&callbackContext->link);
};

context->dartMethodPtr()->matchImageSnapshot(callbackContext, context->contextId(), blob->bytes(), blob->size(),
Expand Down
15 changes: 12 additions & 3 deletions bridge/test/kraken_test_env.cc
Original file line number Diff line number Diff line change
Expand Up @@ -164,11 +164,21 @@ NativeString* TEST_platformBrightness(int32_t contextId) {
return nullptr;
}

void TEST_toBlob(void* callbackContext,

void TEST_toBlob(void* ptr,
int32_t contextId,
AsyncBlobCallback blobCallback,
int32_t elementId,
double devicePixelRatio) {}
double devicePixelRatio) {
uint8_t bytes[5] = {
0x01,
0x02,
0x03,
0x04,
0x05
};
blobCallback(ptr, contextId, nullptr, bytes, 5);
}

void TEST_flushUICommand() {}

Expand Down Expand Up @@ -281,7 +291,6 @@ void TEST_mockDartMethods(int32_t contextId, OnJSError onJSError) {
reinterpret_cast<uint64_t>(TEST_clearTimeout),
reinterpret_cast<uint64_t>(TEST_requestAnimationFrame),
reinterpret_cast<uint64_t>(TEST_cancelAnimationFrame),
reinterpret_cast<uint64_t>(TEST_getScreen),
reinterpret_cast<uint64_t>(TEST_toBlob),
reinterpret_cast<uint64_t>(TEST_flushUICommand),
};
Expand Down
Loading

0 comments on commit 9701560

Please sign in to comment.