Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Feat/Kraken Bundle #866

Merged
merged 48 commits into from Dec 7, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
27f1ad9
:recycle: chore: delete invalid code.
answershuto Nov 10, 2021
3f60086
:sparkles: feat: add navigate type to handleNavigationAction.
answershuto Nov 10, 2021
a67065a
:fire: feat: _bundlePath and _bundleURL should be deprecated.
answershuto Nov 10, 2021
6b94986
:bug: fix: set bundle or url should be save to history modeule.
answershuto Nov 10, 2021
55dee63
:sparkles: feat: modify loadURL of widget.
answershuto Nov 10, 2021
59ac7e3
:sparkles: feat: modify history api for add bundleContent.
answershuto Nov 10, 2021
b9344ae
fix: dealwith href.
answershuto Nov 10, 2021
9e7aaf1
:recycle: refactor: refactor api of Kraken Widget to load bundle.
answershuto Nov 11, 2021
4a4710b
:sparkles: resolve should be mustCallSuper.
answershuto Nov 11, 2021
80ee769
:recycle: chore: modify url to src.
answershuto Nov 11, 2021
e64bd77
:recycle: chore: modify kraken widget of main.dart.
answershuto Nov 11, 2021
60034b1
Merge branch 'main' into fix/window_open
answershuto Nov 11, 2021
2910bf3
:white_check_mark: test: modify main of test.
answershuto Nov 11, 2021
a7c84c5
:recycle: chore: dealwith lint.
answershuto Nov 11, 2021
cc5ecfe
:bug: fix: set href should new bundle.
answershuto Nov 11, 2021
d30bcdb
:sparkles: feat: modify api of kraken for plugin test.
answershuto Nov 15, 2021
3b482cd
:bug: fix: href of script should work.
answershuto Nov 15, 2021
2705571
:sparkles: chore: modify main of kraken example.
answershuto Nov 15, 2021
dccc7b6
:recycle: test: modify bundle of test.
answershuto Nov 15, 2021
817fdb9
:recycle: chore: loadURL and loadPath should be deprecated.
answershuto Nov 15, 2021
a872346
:recycle: chore: modify api of widget.
answershuto Nov 15, 2021
7ac7ea3
:recycle: chore: dealwith lint.
answershuto Nov 15, 2021
b74af60
:recycle: chore: dealwith lint.
answershuto Nov 15, 2021
8bc6984
:recycle: chore: modify kraken widget of performance.
answershuto Nov 15, 2021
21474fe
Merge branch 'main' into fix/window_open
answershuto Nov 23, 2021
5aee668
:recycle: chore: dealwith err.
answershuto Nov 23, 2021
13af380
:bug: fix: should use bundle.
answershuto Nov 23, 2021
873f57e
Merge branch 'main' into fix/window_open
answershuto Dec 2, 2021
000f305
:sparkles: feat: add assets protocol.
answershuto Dec 2, 2021
d8081f5
:sparkles: feat: support assets protocol for AssetsBundle.
answershuto Dec 2, 2021
284f8f1
:art: chore: modify fromHref to fromUrl.
answershuto Dec 3, 2021
030b6ca
:art: chore: modify fromContentWithHref to fromWithContent.
answershuto Dec 3, 2021
6c88260
:sparkles: feat: add additionalHttpHeaders to fromUrl of KrakenBundle.
answershuto Dec 3, 2021
42cd8c2
:white_check_mark: test: modify main of test.
answershuto Dec 3, 2021
40df352
:white_check_mark: test: modify script test.
answershuto Dec 3, 2021
915eeba
:white_check_mark: test: modify test of plugin.
answershuto Dec 3, 2021
a97715a
:white_check_mark: test: modify test of performance.
answershuto Dec 3, 2021
7ad8ada
:art: chore: modify additionalHttpHeaders to _additionalHttpHeaders.
answershuto Dec 3, 2021
37647c9
:art: chore: modify fromWithContent to fromContent.
answershuto Dec 3, 2021
ae0dc1b
:art: chore: modify fromByteCode to fromBytecode.
answershuto Dec 3, 2021
7637bdc
:art: chore: modify byteCode to bytecode.
answershuto Dec 3, 2021
2638f19
:sparkles: feat: modify bundle for launch.
answershuto Dec 3, 2021
23e9b9f
:art: chore: remove the blank space.
answershuto Dec 3, 2021
f2465b1
:art: chore: bundle is not required.
answershuto Dec 3, 2021
3b6fd59
:art: chore: deal with lint.
answershuto Dec 3, 2021
abf0dcc
:sparkles: feat: use bundle replace src.
answershuto Dec 3, 2021
281ccf0
:art: chore: dealwith lint.
answershuto Dec 3, 2021
5aa6671
:white_check_mark: test: modify test of plugin.
answershuto Dec 6, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 0 additions & 3 deletions bridge/bindings/qjs/bom/window.cc
Expand Up @@ -35,7 +35,6 @@ JSClassID Window::classId() {
}

JSValue Window::open(QjsContext* ctx, JSValue this_val, int argc, JSValue* argv) {
JSValue url = argv[0];
auto window = static_cast<WindowInstance*>(JS_GetOpaque(this_val, Window::classId()));
NativeValue arguments[] = {jsValueToNativeValue(ctx, argv[0])};
return window->callNativeMethods("open", 1, arguments);
Expand All @@ -46,8 +45,6 @@ JSValue Window::scrollTo(QjsContext* ctx, JSValue this_val, int argc, JSValue* a
return window->callNativeMethods("scroll", 2, arguments);
}
JSValue Window::scrollBy(QjsContext* ctx, JSValue this_val, int argc, JSValue* argv) {
JSValue x = argv[0];
JSValue y = argv[1];
auto window = static_cast<WindowInstance*>(JS_GetOpaque(this_val, Window::classId()));
NativeValue arguments[] = {jsValueToNativeValue(ctx, argv[0]), jsValueToNativeValue(ctx, argv[1])};
return window->callNativeMethods("scrollBy", 2, arguments);
Expand Down
3 changes: 2 additions & 1 deletion integration_tests/lib/main.dart
Expand Up @@ -6,6 +6,7 @@ import 'package:kraken/css.dart';
import 'package:kraken/bridge.dart';
import 'package:kraken/dom.dart';
import 'package:kraken/foundation.dart';
import 'package:kraken/kraken.dart';
import 'package:kraken/module.dart';
import 'package:kraken/widget.dart';
import 'package:ansicolor/ansicolor.dart';
Expand Down Expand Up @@ -82,7 +83,7 @@ void main() async {
var kraken = krakenMap[i] = Kraken(
viewportWidth: 360,
viewportHeight: 640,
bundleContent: 'console.log("Starting integration tests...")',
bundle: KrakenBundle.fromContent('console.log("Starting integration tests...")'),
disableViewportWidthAssertion: true,
disableViewportHeightAssertion: true,
javaScriptChannel: javaScriptChannel,
Expand Down
3 changes: 2 additions & 1 deletion integration_tests/lib/plugin.dart
Expand Up @@ -7,6 +7,7 @@ import 'package:kraken/dom.dart';
import 'package:kraken/foundation.dart';
import 'package:kraken/module.dart';
import 'package:kraken/widget.dart';
import 'package:kraken/launcher.dart';
import 'package:ansicolor/ansicolor.dart';
import 'package:path/path.dart' as path;
import 'bridge/from_native.dart';
Expand Down Expand Up @@ -68,7 +69,7 @@ void main() async {
var kraken = krakenMap[i] = Kraken(
viewportWidth: 360,
viewportHeight: 640,
bundleContent: 'console.log("Starting Plugin tests...")',
bundle: KrakenBundle.fromContent('console.log("Starting Plugin tests...")'),
disableViewportWidthAssertion: true,
disableViewportHeightAssertion: true,
uriParser: IntegrationTestUriParser(),
Expand Down
2 changes: 1 addition & 1 deletion integration_tests/specs/dom/elements/script.ts
Expand Up @@ -4,7 +4,7 @@ describe('script element', () => {
const p = <p>Should see hello below:</p>;
document.body.appendChild(p);
var x = document.createElement('script');
x.src = 'assets/hello.js';
x.src = 'assets://assets/hello.js';
document.head.appendChild(x);
x.onload = async () => {
await snapshot();
Expand Down
4 changes: 2 additions & 2 deletions kraken/example/lib/main.dart
Expand Up @@ -63,7 +63,7 @@ class _MyHomePageState extends State<MyBrowser> {
controller: textEditingController,
onSubmitted: (value) {
textEditingController.text = value;
_kraken?.loadURL(value);
_kraken?.loadBundle(KrakenBundle.fromUrl(value));
},
decoration: InputDecoration(
hintText: 'Enter a app url',
Expand Down Expand Up @@ -92,7 +92,7 @@ class _MyHomePageState extends State<MyBrowser> {
devToolsService: ChromeDevToolsService(),
viewportWidth: viewportSize.width - queryData.padding.horizontal,
viewportHeight: viewportSize.height - appBar.preferredSize.height - queryData.padding.vertical,
bundleURL: 'assets/bundle.js',
bundle: KrakenBundle.fromUrl('assets://assets/bundle.js'),
),
));
}
Expand Down
7 changes: 5 additions & 2 deletions kraken/lib/src/dom/elements/head.dart
Expand Up @@ -9,6 +9,7 @@ import 'package:flutter/scheduler.dart';
import 'package:kraken/bridge.dart';
import 'package:kraken/css.dart';
import 'package:kraken/dom.dart';
import 'package:kraken/kraken.dart';
import 'package:kraken/launcher.dart';

// Children of the <head> element all have display:none
Expand Down Expand Up @@ -73,7 +74,8 @@ class ScriptElement extends Element {
// Must
if (src.isNotEmpty && isConnected && (type == _JAVASCRIPT_MIME || type == _JAVASCRIPT_MODULE)) {
try {
KrakenBundle bundle = await KrakenBundle.getBundle(src, contextId: elementManager.contextId);
KrakenBundle bundle = KrakenBundle.fromUrl(src);
await bundle.resolve(elementManager.contextId);
await bundle.eval(elementManager.contextId);
// Successful load.
SchedulerBinding.instance!.addPostFrameCallback((_) {
Expand Down Expand Up @@ -108,7 +110,8 @@ class ScriptElement extends Element {
int contextId = elementManager.contextId;
KrakenController? controller = KrakenController.getControllerOfJSContextId(contextId);
if (controller != null) {
KrakenBundle bundle = await KrakenBundle.getBundle(controller.href, contentOverride: script, contextId: contextId);
KrakenBundle bundle = KrakenBundle.fromContent(script, url: controller.href);
bundle.resolve(contextId);
await bundle.eval(elementManager.contextId);
}
}
Expand Down
2 changes: 1 addition & 1 deletion kraken/lib/src/dom/window.dart
Expand Up @@ -25,7 +25,7 @@ class Window extends EventTarget {

static void _open(ElementManager elementManager, String url) {
KrakenController rootController = elementManager.controller.view.rootController;
String? sourceUrl = rootController.bundleURL ?? rootController.bundlePath;
String? sourceUrl = rootController.href;

elementManager.controller.view.handleNavigationAction(sourceUrl, url, KrakenNavigationType.navigate);
}
Expand Down
106 changes: 64 additions & 42 deletions kraken/lib/src/launcher/bundle.dart
Expand Up @@ -22,6 +22,8 @@ const String BUNDLE_PATH = 'KRAKEN_BUNDLE_PATH';
const String ENABLE_DEBUG = 'KRAKEN_ENABLE_DEBUG';
const String ENABLE_PERFORMANCE_OVERLAY = 'KRAKEN_ENABLE_PERFORMANCE_OVERLAY';

const String ASSETS_PROROCOL = 'assets://';

String? getBundleURLFromEnv() {
return Platform.environment[BUNDLE_URL];
}
Expand All @@ -46,17 +48,21 @@ String getAcceptHeader() {
}

bool isAssetAbsolutePath(String path) {
return path.indexOf('assets/') == 0;
return path.startsWith(ASSETS_PROROCOL);
}

abstract class KrakenBundle {
KrakenBundle(this.url);
KrakenBundle(this.src);

// Unique resource locator.
final Uri url;
final String src;

// Customize the parsed uri by uriParser.
Uri? uri;

late ByteData rawBundle;
// JS Content in UTF-8 bytes.
Uint8List? byteCode;
Uint8List? bytecode;
// JS Content is String
String? content;
// JS line offset, default to 0.
Expand All @@ -69,60 +75,64 @@ abstract class KrakenBundle {
// Bundle contentType.
ContentType contentType = ContentType.binary;

Future<void> resolve();

static Future<KrakenBundle> getBundle(String path, { String? contentOverride, required int contextId }) async {
KrakenBundle bundle;

@mustCallSuper
Future<void> resolve(int contextId) async {
if (kDebugMode) {
print('Kraken getting bundle for contextId: $contextId, path: $path');
print('Kraken getting bundle for contextId: $contextId, src: $src');
}

Uri uri = Uri.parse(path);
uri = Uri.parse(src);
KrakenController? controller = KrakenController.getControllerOfJSContextId(contextId);
if (controller != null && !isAssetAbsolutePath(path)) {
uri = controller.uriParser!.resolve(Uri.parse(controller.href), uri);
if (controller != null && !isAssetAbsolutePath(src)) {
uri = controller.uriParser!.resolve(Uri.parse(controller.href), uri!);
}

if (contentOverride != null && contentOverride.isNotEmpty) {
bundle = RawBundle.fromString(contentOverride, uri);
} else if (uri.isScheme('HTTP') || uri.isScheme('HTTPS')) {
bundle = NetworkBundle(uri, contextId: contextId);
isResolved = true;
}

static KrakenBundle fromUrl(String url, { Map<String, String>? additionalHttpHeaders }) {
if (isAssetAbsolutePath(url)) {
return AssetsBundle(url);
} else {
bundle = AssetsBundle(uri);
return NetworkBundle(url, additionalHttpHeaders: additionalHttpHeaders);
}
}

await bundle.resolve();
static KrakenBundle fromContent(String content, { String url = '' }) {
return RawBundle.fromString(content, url);
}

return bundle;
static KrakenBundle fromBytecode(Uint8List bytecode, { String url = '' }) {
return RawBundle.fromBytecode(bytecode, url);
}


Future<void> eval(int contextId) async {
if (!isResolved) await resolve();
if (!isResolved) await resolve(contextId);

if (kProfileMode) {
PerformanceTiming.instance().mark(PERF_JS_BUNDLE_EVAL_START);
}

// For raw javascript code or bytecode from API directly.
if (content != null) {
evaluateScripts(contextId, content!, url.toString(), lineOffset);
} else if (byteCode != null) {
evaluateQuickjsByteCode(contextId, byteCode!);
evaluateScripts(contextId, content!, src, lineOffset);
} else if (bytecode != null) {
evaluateQuickjsByteCode(contextId, bytecode!);
}

// For javascript code, HTML or bytecode from networks and hardware disk.
else if (contentType.mimeType == ContentType.html.mimeType || url.toString().contains('.html')) {
else if (contentType.mimeType == ContentType.html.mimeType || src.contains('.html')) {
String code = _resolveStringFromData(rawBundle);
// parse html.
parseHTML(contextId, code);
} else if (isByteCodeSupported(contentType.mimeType, url.toString())) {
} else if (isByteCodeSupported(contentType.mimeType, src)) {
Uint8List buffer = rawBundle.buffer.asUint8List();
evaluateQuickjsByteCode(contextId, buffer);
} else {
String code = _resolveStringFromData(rawBundle);
// eval JavaScript.
evaluateScripts(contextId, code, url.toString(), lineOffset);
evaluateScripts(contextId, code, src, lineOffset);
}

if (kProfileMode) {
Expand All @@ -132,33 +142,37 @@ abstract class KrakenBundle {
}

class RawBundle extends KrakenBundle {
RawBundle.fromString(String content, Uri url)
RawBundle.fromString(String content, String url)
: super(url) {
this.content = content;
}

RawBundle.fromByteCode(Uint8List byteCode, Uri url) : super(url) {
this.byteCode = byteCode;
RawBundle.fromBytecode(Uint8List bytecode, String url)
: super(url) {
this.bytecode = bytecode;
}

@override
Future<void> resolve() async {
Future<void> resolve(int contextId) async {
super.resolve(contextId);
isResolved = true;
}
}

class NetworkBundle extends KrakenBundle {
int contextId;
NetworkBundle(Uri url, { required this.contextId })
NetworkBundle(String url, { this.additionalHttpHeaders })
: super(url);

Map<String, String>? additionalHttpHeaders = {};
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

没有其他人用, 这个可以私有的


@override
Future<void> resolve() async {
Future<void> resolve(int contextId) async {
super.resolve(contextId);
KrakenController controller = KrakenController.getControllerOfJSContextId(contextId)!;
Uri baseUrl = Uri.parse(controller.href);
NetworkAssetBundle bundle = NetworkAssetBundle(controller.uriParser!.resolve(baseUrl, url), contextId: contextId);
NetworkAssetBundle bundle = NetworkAssetBundle(controller.uriParser!.resolve(baseUrl, Uri.parse(src)), contextId: contextId, additionalHttpHeaders: additionalHttpHeaders);
bundle.httpClient.userAgent = getKrakenInfo().userAgent;
String absoluteURL = url.toString();
String absoluteURL = src;
rawBundle = await bundle.load(absoluteURL);
contentType = bundle.contentType;
isResolved = true;
Expand All @@ -177,13 +191,15 @@ String _resolveStringFromData(ByteData data) {
class NetworkAssetBundle extends AssetBundle {
/// Creates an network asset bundle that resolves asset keys as URLs relative
/// to the given base URL.
NetworkAssetBundle(Uri baseUrl, { required this.contextId })
NetworkAssetBundle(Uri baseUrl, { required this.contextId, additionalHttpHeaders })
: _baseUrl = baseUrl,
_additionalHttpHeaders = additionalHttpHeaders,
httpClient = HttpClient();

final Uri _baseUrl;
final int contextId;
final HttpClient httpClient;
final Map<String, String>? _additionalHttpHeaders;
ContentType contentType = ContentType.binary;

Uri _urlFromKey(String key) => _baseUrl.resolve(key);
Expand All @@ -192,6 +208,9 @@ class NetworkAssetBundle extends AssetBundle {
Future<ByteData> load(String key) async {
final HttpClientRequest request = await httpClient.getUrl(_urlFromKey(key));
request.headers.set('Accept', getAcceptHeader());
if (_additionalHttpHeaders != null) {
_additionalHttpHeaders?.forEach(request.headers.set);
}
KrakenHttpOverrides.setContextHeader(request.headers, contextId);

final HttpClientResponse response = await request.close();
Expand Down Expand Up @@ -223,15 +242,18 @@ class NetworkAssetBundle extends AssetBundle {
}

class AssetsBundle extends KrakenBundle {
AssetsBundle(Uri url)
AssetsBundle(String url)
: super(url);

@override
Future<void> resolve() async {
Future<KrakenBundle> resolve(int contextId) async {
super.resolve(contextId);
// JSBundle get default bundle manifest.
manifest = AppManifest();
String localPath = url.toString();
rawBundle = await rootBundle.load(localPath);
isResolved = true;
if (isAssetAbsolutePath(src)) {
String localPath = src.substring(ASSETS_PROROCOL.length);
rawBundle = await rootBundle.load(localPath);
}
return this;
}
}