Skip to content

Commit 4f3a0d7

Browse files
authored
feat(WinterCG): URL & URLSearchParams (#1801)
1 parent f43f591 commit 4f3a0d7

File tree

13 files changed

+24190
-1
lines changed

13 files changed

+24190
-1
lines changed

Diff for: test-app/app/src/main/assets/app/mainpage.js

+3-1
Original file line numberDiff line numberDiff line change
@@ -69,4 +69,6 @@ require("./tests/testPackagePrivate");
6969
require("./tests/kotlin/properties/testPropertiesSupport.js");
7070
require('./tests/testNativeTimers');
7171
require("./tests/testPostFrameCallback");
72-
require("./tests/console/logTests.js");
72+
require("./tests/console/logTests.js");
73+
require('./tests/testURLImpl.js');
74+
require('./tests/testURLSearchParamsImpl.js');
+31
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
describe("Test URL ", function () {
2+
3+
it("Test invalid URL parsing", function(){
4+
var exceptionCaught = false;
5+
try {
6+
const url = new URL('');
7+
}catch(e){
8+
exceptionCaught = true;
9+
}
10+
expect(exceptionCaught).toBe(true);
11+
});
12+
13+
it("Test valid URL parsing", function(){
14+
var exceptionCaught = false;
15+
try {
16+
const url = new URL('https://google.com');
17+
}catch(e){
18+
exceptionCaught = true;
19+
}
20+
expect(exceptionCaught).toBe(false);
21+
});
22+
23+
24+
it("Test URL fields", function(){
25+
var exceptionCaught = false;
26+
const url = new URL('https://google.com');
27+
expect(url.protocol).toBe('https:');
28+
expect(url.hostname).toBe('google.com');
29+
});
30+
31+
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
describe("Test URLSearchParams ", function () {
2+
const fooBar = "foo=1&bar=2";
3+
it("Test URLSearchParams keys", function(){
4+
const params = new URLSearchParams(fooBar);
5+
const keys = params.keys();
6+
expect(keys[0]).toBe("foo");
7+
expect(keys[1]).toBe("bar");
8+
});
9+
10+
it("Test URLSearchParams values", function(){
11+
const params = new URLSearchParams(fooBar);
12+
const values = params.values();
13+
expect(values[0]).toBe("1");
14+
expect(values[1]).toBe("2");
15+
});
16+
17+
18+
it("Test URLSearchParams entries", function(){
19+
const params = new URLSearchParams(fooBar);
20+
const entries = params.entries();
21+
expect(entries[0][0]).toBe("foo");
22+
expect(entries[0][1]).toBe("1");
23+
24+
expect(entries[1][0]).toBe("bar");
25+
expect(entries[1][1]).toBe("2");
26+
27+
});
28+
29+
30+
it("Test URLSearchParams size", function(){
31+
const params = new URLSearchParams(fooBar);
32+
expect(params.size).toBe(2);
33+
});
34+
35+
it("Test URLSearchParams append", function(){
36+
const params = new URLSearchParams(fooBar);
37+
params.append("first", "Osei");
38+
expect(params.get("first")).toBe("Osei");
39+
});
40+
41+
42+
it("Test URLSearchParams delete", function(){
43+
const params = new URLSearchParams(fooBar);
44+
params.append("first", "Osei");
45+
params.delete("first");
46+
expect(params.get("first")).toBe(undefined);
47+
});
48+
49+
50+
it("Test URLSearchParams has", function(){
51+
const params = new URLSearchParams(fooBar);
52+
expect(params.has("foo")).toBe(true);
53+
});
54+
55+
it("Test URLSearchParams changes propagates to URL parent", function(){
56+
const toBe = 'https://github.com/triniwiz?first=Osei';
57+
const url = new URL('https://github.com/triniwiz');
58+
const params = url.searchParams;
59+
console.log(params);
60+
params.set('first', 'Osei');
61+
expect(url.toString()).toBe(toBe);
62+
});
63+
64+
});

Diff for: test-app/runtime/CMakeLists.txt

+4
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ include_directories(
5252
src/main/cpp
5353
src/main/cpp/include
5454
src/main/cpp/v8_inspector
55+
src/main/cpp/ada
5556
)
5657

5758
if (OPTIMIZED_BUILD OR OPTIMIZED_WITH_INSPECTOR_BUILD)
@@ -137,6 +138,9 @@ add_library(
137138
src/main/cpp/conversions/objects/JSToJavaObjectsConverter.cpp
138139
src/main/cpp/conversions/arrays/JSToJavaArraysConverter.cpp
139140
src/main/cpp/conversions/primitives/JSToJavaPrimitivesConverter.cpp
141+
src/main/cpp/ada/ada.cpp
142+
src/main/cpp/URLImpl.cpp
143+
src/main/cpp/URLSearchParamsImpl.cpp
140144

141145
# V8 inspector source files will be included only in Release mode
142146
${INSPECTOR_SOURCES}

Diff for: test-app/runtime/src/main/cpp/Runtime.cpp

+73
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,8 @@
3131
#include <thread>
3232
#include "File.h"
3333
#include "ModuleBinding.h"
34+
#include "URLImpl.h"
35+
#include "URLSearchParamsImpl.h"
3436

3537
#ifdef APPLICATION_IN_DEBUG
3638
// #include "NetworkDomainCallbackHandlers.h"
@@ -519,6 +521,9 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native
519521
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__runOnMainThread"), FunctionTemplate::New(isolate, CallbackHandlers::RunOnMainThreadCallback));
520522
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__postFrameCallback"), FunctionTemplate::New(isolate, CallbackHandlers::PostFrameCallback));
521523
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "__removeFrameCallback"), FunctionTemplate::New(isolate, CallbackHandlers::RemoveFrameCallback));
524+
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "URL"), URLImpl::GetCtor(isolate));
525+
globalTemplate->Set(ArgConverter::ConvertToV8String(isolate, "URLSearchParams"), URLSearchParamsImpl::GetCtor(isolate));
526+
522527
/*
523528
* Attach `Worker` object constructor only to the main thread (isolate)'s global object
524529
* Workers should not be created from within other Workers, for now
@@ -586,10 +591,78 @@ Isolate* Runtime::PrepareV8Runtime(const string& filesPath, const string& native
586591

587592
Local<Context> context = Context::New(isolate, nullptr, globalTemplate);
588593

594+
auto blob_methods = R"js(
595+
const BLOB_STORE = new Map();
596+
URL.createObjectURL = function (object, options = null) {
597+
try {
598+
if (object instanceof Blob || object instanceof File) {
599+
const id = java.util.UUID.randomUUID().toString();
600+
const ret = `blob:nativescript/${id}`;
601+
BLOB_STORE.set(ret, {
602+
blob: object,
603+
type: object?.type,
604+
ext: options?.ext,
605+
});
606+
return ret;
607+
}
608+
} catch (error) {
609+
return null;
610+
}
611+
return null;
612+
};
613+
URL.revokeObjectURL = function (url) {
614+
BLOB_STORE.delete(url);
615+
};
616+
const InternalAccessor = class {};
617+
InternalAccessor.getData = function (url) {
618+
return BLOB_STORE.get(url);
619+
};
620+
URL.InternalAccessor = InternalAccessor;
621+
Object.defineProperty(URL.prototype, 'searchParams', {
622+
get() {
623+
if (this._searchParams == null) {
624+
this._searchParams = new URLSearchParams(this.search);
625+
Object.defineProperty(this._searchParams, '_url', {
626+
enumerable: false,
627+
writable: false,
628+
value: this,
629+
});
630+
this._searchParams._append = this._searchParams.append;
631+
this._searchParams.append = function (name, value) {
632+
this._append(name, value);
633+
this._url.search = this.toString();
634+
};
635+
this._searchParams._delete = this._searchParams.delete;
636+
this._searchParams.delete = function (name) {
637+
this._delete(name);
638+
this._url.search = this.toString();
639+
};
640+
this._searchParams._set = this._searchParams.set;
641+
this._searchParams.set = function (name, value) {
642+
this._set(name, value);
643+
this._url.search = this.toString();
644+
};
645+
this._searchParams._sort = this._searchParams.sort;
646+
this._searchParams.sort = function () {
647+
this._sort();
648+
this._url.search = this.toString();
649+
};
650+
}
651+
return this._searchParams;
652+
},
653+
});
654+
)js";
655+
656+
589657
auto global = context->Global();
590658

591659
v8::Context::Scope contextScope{context};
592660

661+
v8::Local<v8::Script> script;
662+
v8::Script::Compile(context, ArgConverter::ConvertToV8String(isolate, blob_methods)).ToLocal(&script);
663+
664+
v8::Local<v8::Value> out;
665+
script->Run(context).ToLocal(&out);
593666
m_objectManager->Init(isolate);
594667

595668
m_module.Init(isolate, callingDir);

0 commit comments

Comments
 (0)