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

如何把字符串通过dart代码转成quickjs bytecode #102

Open
1 task done
zjt123 opened this issue Nov 5, 2022 · 15 comments
Open
1 task done

如何把字符串通过dart代码转成quickjs bytecode #102

zjt123 opened this issue Nov 5, 2022 · 15 comments
Labels
bug Something isn't working

Comments

@zjt123
Copy link
Collaborator

zjt123 commented Nov 5, 2022

Affected version

main

No same issues found.

  • Yes, I search all issues but not found.

Steps to Reproduce

字符串是动态的,需要把这个字符串通过dart代码转成quickjs bytecode追加到test.kbc1文件的内容里面。

Code example

字符串是动态的,需要把这个字符串转成quickjs bytecode追加到test.kbc1文件的内容里面。

String myStr = "window.a = 'hello'"// test.kbc1会读取这个window.a值
WebfBundle entrypoint = _entrypoint!;
Uint8List data = entrypoint.data!;
List targetData = data as List;
List myStrList = utf8.encode(myStr);
data = Uint8List.fromList(myStrList + targetData);

执行evaluateQuickjsByteCode是有问题的,执行异常。 如果test.kbc1是test.js的话 用evaluateScripts方法执行的话是没问题的。

是不是我的代码转换的不对?应该如何转换?

Expected results

如何把字符串通过正确的dart代码转成quickjs bytecode??

Actual results

如何把字符串通过正确的dart代码转成quickjs bytecode??

@zjt123 zjt123 added the bug Something isn't working label Nov 5, 2022
@andycall
Copy link
Member

andycall commented Nov 6, 2022

QuickJS bytecode can only be exported from C API. You can copy the source code in the node-qjsc plugin and export a C API to the dart.

QuickJS ByteCode 的代码需要用 QuickJS API 才能够导出来,你需要参考一下 node-qjsc 在 Bridge 层实现一下, 然后暴露给 Dart 使用

@zjt123
Copy link
Collaborator Author

zjt123 commented Nov 7, 2022

QuickJS bytecode can only be exported from C API. You can copy the source code in the node-qjsc plugin and export a C API to the dart.

QuickJS ByteCode 的代码需要用 QuickJS API 才能够导出来,你需要参考一下 node-qjsc 在 Bridge 层实现一下, 然后暴露给 Dart 使用

我在bridge里面,封装了一层,直接返回bytes指针。但是不知道 在dart层应该怎么获取到,看着是报错的,说没有定义的nativeType。辛苦帮我看看应该怎么写?

bridge层:========================

uint8_t* quickjsDumpByteCode(int32_t contextId, const char* code) {
assert(checkPage(contextId) && "evaluateScripts: contextId is not valid");
size_t byteLen;
auto context = static_castwebf::WebFPage*(getPage(contextId));
context->evaluateByteCode(bytes, byteLen);
uint8_t* bytes = context->dumpByteCode(code, strlen(code), "vm://", &byteLen);
return bytes;
}

to_native.dart:========================

typedef NativeQuickjsDumpByteCode = Uint8List Function(
Int32 contextId, Pointer code);
typedef DartQuickjsDumpByteCode = Uint8List Function(
int contextId, Pointer code);

final DartQuickjsDumpByteCode _quickjsDumpByteCode = WebFDynamicLibrary
.ref
.lookup<NativeFunction>('quickjsDumpByteCode')
.asFunction();

Uint8List? quickjsDumpByteCode(int contextId, String code) {
if (WebFController.getControllerOfJSContextId(contextId) == null) {
return null;
}
Pointer nativeCode = code.toNativeUtf8();
Uint8List byteCode = _quickjsDumpByteCode(contextId, nativeCode);
malloc.free(nativeCode);
return byteCode;
}

报错信息========================

The type argument for the pointer 'NativeFunction<Uint8List Function(Int32, Pointer)>' must be a valid 'NativeFunction' in order to use 'asFunction'. Try changing the function argument in 'NativeFunction' to only use NativeTypes.

@andycall
Copy link
Member

andycall commented Nov 7, 2022

typedef NativeQuickjsDumpByteCode = Pointer<Uint8> Function(
    Int32 contextId, Pointer code);
typedef DartQuickjsDumpByteCode = Pointer<Uint8> Function(
    int contextId, Pointer code);

final DartQuickjsDumpByteCode _quickjsDumpByteCode = WebFDynamicLibrary
    .ref
    .lookup<NativeFunction<NativeQuickjsDumpByteCode>>('quickjsDumpByteCode')
    .asFunction();

Pointer<Uint8> quickjsDumpByteCode(int contextId, String code) {
  if (WebFController.getControllerOfJSContextId(contextId) == null) {
    return nullptr;
  }
  Pointer nativeCode = code.toNativeUtf8();
  Pointer<Uint8> byteCode = _quickjsDumpByteCode(contextId, nativeCode);
  malloc.free(nativeCode);
  return byteCode;
}

@zjt123
Copy link
Collaborator Author

zjt123 commented Nov 7, 2022

typedef NativeQuickjsDumpByteCode = Pointer<Uint8> Function(
    Int32 contextId, Pointer code);
typedef DartQuickjsDumpByteCode = Pointer<Uint8> Function(
    int contextId, Pointer code);

final DartQuickjsDumpByteCode _quickjsDumpByteCode = WebFDynamicLibrary
    .ref
    .lookup<NativeFunction<NativeQuickjsDumpByteCode>>('quickjsDumpByteCode')
    .asFunction();

Pointer<Uint8> quickjsDumpByteCode(int contextId, String code) {
  if (WebFController.getControllerOfJSContextId(contextId) == null) {
    return nullptr;
  }
  Pointer nativeCode = code.toNativeUtf8();
  Pointer<Uint8> byteCode = _quickjsDumpByteCode(contextId, nativeCode);
  malloc.free(nativeCode);
  return byteCode;
}

image
还是不行,是不是哪里搞错了?但有个疑问点,为什么kbc1文件读取出来的 entrypoint.data 是10进制数的 数组,我这边通过c把字符串传出来的是 16进制数的数组。我是这么调用的

  String  test = "xxx";
  Pointer<Uint8> byteCodePointer = quickjsDumpByteCode(contextId, test);
  Uint8List byteCode = byteCodePointer.asTypedList(test.length);

@zjt123
Copy link
Collaborator Author

zjt123 commented Nov 8, 2022

我用最简单的试了下,确保我写的quickjsDumpByteCode是没问题的。

kbc1文件原来的内容是 console.log('i am 11'); 从 entrypoint.data 获取 到 Uint8List data
我拼接的字符串内容是 console.log('i am 00'); 从 我自己写的 quickjsDumpByteCode(contextId, "console.log('i am 00');") 获取到 Uint8List? uint8list;

拼接姿势:
data = Uint8List.fromList((uint8list as List) + ( entrypoint.data as List));

拼接后传入quickjs解析执行
evaluateQuickjsByteCode(contextId, data);

输出结果。只会输出i am 00

同理如果 拼接顺序反过来entrypoint.data 在前面,uint8list在后面,只会输出 i am 11.

也就是说 字符串转bytecode是没问题的。现在应该是拼接方式不对。

@andycall 辛苦帮忙看看应该是怎么拼接的。才能输出 两个i am 11 和 i am 00。

@andycall
Copy link
Member

andycall commented Nov 8, 2022

Uint8List byteCode = byteCodePointer.asTypedList(test.length);

byteCodePointer.asTypedList( ) 应该传递 ByteCode 的 length,不是字符串的 Length
byteCodePointer.asTypedList( ) should pass quickjs bytecode's length, not the length of string.

@andycall
Copy link
Member

andycall commented Nov 8, 2022

ByteCode 是无法被拼接的,它有独立的 Layout 内存结构,只能重新生成。
Bytecode can't be merged with another bytecode. It has indenpendent memory layout, only can be re-generated.

@zjt123
Copy link
Collaborator Author

zjt123 commented Nov 8, 2022

ByteCode 是无法被拼接的,它有独立的 Layout 内存结构,只能重新生成。 Bytecode can't be merged with another bytecode. It has indenpendent memory layout, only can be re-generated.

那原来kbc1文件的bytecode转换成字符串再字符串拼接,再转成bytecode,这种方式呢,能搞不?

String kbc1Str = new String.fromCharCodes(entrypoint.data!); //这样转好像也不多,和原来的字符串不一样。你知道怎么把bytecode转字符串吗?

String.fromCharCodes 是这样的:
���console�log�i am 11�internal://�� �����¢�8ÒBÓ�Ô$�Ë(ª��

@andycall
Copy link
Member

andycall commented Nov 8, 2022

Bytecode 无法反向转换,只能 String -> Bytecode
Bytecode cannot be reverse converted, only String -> Bytecode

@andycall
Copy link
Member

andycall commented Nov 8, 2022

你为啥会需要这个功能,可以描述一下你的场景吗?
Why would you needs this feature? Can you describe your scenario ?

@zjt123
Copy link
Collaborator Author

zjt123 commented Nov 8, 2022

你为啥会需要这个功能,可以描述一下你的场景吗?
Why would you needs this feature? Can you describe your scenario ?

有些信息是从外部传入的。需要拼接起来才能搞。例如全局的数据模型。

@andycall
Copy link
Member

andycall commented Nov 8, 2022

Maybe registerPluginByteCode can solve your problems.
可以试一下 registerPluginByteCode 这个 API

@zjt123
Copy link
Collaborator Author

zjt123 commented Nov 9, 2022

Maybe registerPluginByteCode can solve your problems. 可以试一下 registerPluginByteCode 这个 API

好像不太行 ,是不是我用法不对?
我是在evaluateQuickjsByteCode(contextId, entrypoint.data!);前 ,
调用
Uint8List mytest = quickjsDumpByteCode(contextId, "console.log('i am 00');")
registerPluginByteCode(mytest, "test");

@andycall
Copy link
Member

andycall commented Nov 9, 2022

或许你应该改变一下思路,比如利用多个 script 标签来分别加载多个 bytecode,这样就不用考虑拼接的事情了。
Maybe you can change your mind, such as use multiple script element to load more bytecode files, and no more concatenate needed.

alibaba/rax#2396 (comment)

@zjt123
Copy link
Collaborator Author

zjt123 commented Nov 9, 2022

或许你应该改变一下思路,比如利用多个 script 标签来分别加载多个 bytecode,这样就不用考虑拼接的事情了。 Maybe you can change your mind, such as use multiple script element to load more bytecode files, and no more concatenate needed.

alibaba/rax#2396 (comment)

谢谢 你的思路。之前就是用这种方式的。但是嫌他请求好几次太慢了。所以想搞成拼接的方式

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working
Projects
None yet
Development

No branches or pull requests

2 participants