+
+ Line data Source code
+
+ 1 : /*
+ 2 : * @Description: ffi
+ 3 : * @Author: ekibun
+ 4 : * @Date: 2020-09-19 10:29:04
+ 5 : * @LastEditors: ekibun
+ 6 : * @LastEditTime: 2020-12-02 11:14:35
+ 7 : */
+ 8 : import 'dart:ffi';
+ 9 : import 'dart:io';
+ 10 : import 'dart:isolate';
+ 11 : import 'package:ffi/ffi.dart';
+ 12 :
+ 13 : extension ListFirstWhere<T> on Iterable<T> {
+ 14 3 : T? firstWhereOrNull(bool Function(T) test) {
+ 15 : try {
+ 16 3 : return firstWhere(test);
+ 17 3 : } on StateError {
+ 18 : return null;
+ 19 : }
+ 20 : }
+ 21 : }
+ 22 :
+ 23 : abstract class JSRef {
+ 24 : int _refCount = 0;
+ 25 3 : void dup() {
+ 26 6 : _refCount++;
+ 27 : }
+ 28 :
+ 29 3 : void free() {
+ 30 6 : _refCount--;
+ 31 9 : if (_refCount < 0) destroy();
+ 32 : }
+ 33 :
+ 34 : void destroy();
+ 35 :
+ 36 3 : static void freeRecursive(dynamic obj) {
+ 37 7 : _callRecursive(obj, (ref) => ref.free());
+ 38 : }
+ 39 :
+ 40 3 : static void dupRecursive(dynamic obj) {
+ 41 7 : _callRecursive(obj, (ref) => ref.dup());
+ 42 : }
+ 43 :
+ 44 3 : static void _callRecursive(
+ 45 : dynamic obj,
+ 46 : void Function(JSRef) cb, [
+ 47 : Set? cache,
+ 48 : ]) {
+ 49 : if (obj == null) return;
+ 50 : if (cache == null) cache = Set();
+ 51 3 : if (cache.contains(obj)) return;
+ 52 3 : if (obj is List) {
+ 53 3 : cache.add(obj);
+ 54 12 : List.from(obj).forEach((e) => _callRecursive(e, cb, cache));
+ 55 : }
+ 56 3 : if (obj is Map) {
+ 57 2 : cache.add(obj);
+ 58 10 : obj.values.toList().forEach((e) => _callRecursive(e, cb, cache));
+ 59 : }
+ 60 3 : if (obj is JSRef) {
+ 61 2 : cb(obj);
+ 62 : }
+ 63 : }
+ 64 : }
+ 65 :
+ 66 : abstract class JSRefLeakable {}
+ 67 :
+ 68 : class JSEvalFlag {
+ 69 : static const GLOBAL = 0 << 0;
+ 70 : static const MODULE = 1 << 0;
+ 71 : }
+ 72 :
+ 73 : class JSChannelType {
+ 74 : static const METHON = 0;
+ 75 : static const MODULE = 1;
+ 76 : static const PROMISE_TRACK = 2;
+ 77 : static const FREE_OBJECT = 3;
+ 78 : }
+ 79 :
+ 80 : class JSProp {
+ 81 : static const CONFIGURABLE = (1 << 0);
+ 82 : static const WRITABLE = (1 << 1);
+ 83 : static const ENUMERABLE = (1 << 2);
+ 84 : static const C_W_E = (CONFIGURABLE | WRITABLE | ENUMERABLE);
+ 85 : }
+ 86 :
+ 87 : class JSTag {
+ 88 : static const FIRST = -11; /* first negative tag */
+ 89 : static const BIG_DECIMAL = -11;
+ 90 : static const BIG_INT = -10;
+ 91 : static const BIG_FLOAT = -9;
+ 92 : static const SYMBOL = -8;
+ 93 : static const STRING = -7;
+ 94 : static const MODULE = -3; /* used internally */
+ 95 : static const FUNCTION_BYTECODE = -2; /* used internally */
+ 96 : static const OBJECT = -1;
+ 97 :
+ 98 : static const INT = 0;
+ 99 : static const BOOL = 1;
+ 100 : static const NULL = 2;
+ 101 : static const UNDEFINED = 3;
+ 102 : static const UNINITIALIZED = 4;
+ 103 : static const CATCH_OFFSET = 5;
+ 104 : static const EXCEPTION = 6;
+ 105 : static const FLOAT64 = 7;
+ 106 : }
+ 107 :
+ 108 : abstract class JSValue extends Opaque {}
+ 109 :
+ 110 : abstract class JSContext extends Opaque {}
+ 111 :
+ 112 : abstract class JSRuntime extends Opaque {}
+ 113 :
+ 114 : abstract class JSPropertyEnum extends Opaque {}
+ 115 :
+ 116 15 : final DynamicLibrary _qjsLib = Platform.environment['FLUTTER_TEST'] == 'true'
+ 117 3 : ? (Platform.isWindows
+ 118 3 : ? DynamicLibrary.open('test/build/Debug/ffiquickjs.dll')
+ 119 0 : : Platform.isMacOS
+ 120 0 : ? DynamicLibrary.open('test/build/libffiquickjs.dylib')
+ 121 0 : : DynamicLibrary.open('test/build/libffiquickjs.so'))
+ 122 0 : : (Platform.isWindows
+ 123 0 : ? DynamicLibrary.open('flutter_qjs_plugin.dll')
+ 124 0 : : Platform.isAndroid
+ 125 0 : ? DynamicLibrary.open('libqjs.so')
+ 126 0 : : DynamicLibrary.process());
+ 127 :
+ 128 : /// DLLEXPORT JSValue *jsThrow(JSContext *ctx, JSValue *obj)
+ 129 : final Pointer<JSValue> Function(
+ 130 : Pointer<JSContext> ctx,
+ 131 : Pointer<JSValue> obj,
+ 132 0 : ) jsThrow = _qjsLib
+ 133 : .lookup<
+ 134 : NativeFunction<
+ 135 : Pointer<JSValue> Function(
+ 136 : Pointer<JSContext>,
+ 137 : Pointer<JSValue>,
+ 138 : )>>('jsThrow')
+ 139 : .asFunction();
+ 140 :
+ 141 : /// JSValue *jsEXCEPTION()
+ 142 0 : final Pointer<JSValue> Function() jsEXCEPTION = _qjsLib
+ 143 : .lookup<NativeFunction<Pointer<JSValue> Function()>>('jsEXCEPTION')
+ 144 : .asFunction();
+ 145 :
+ 146 : /// JSValue *jsUNDEFINED()
+ 147 9 : final Pointer<JSValue> Function() jsUNDEFINED = _qjsLib
+ 148 3 : .lookup<NativeFunction<Pointer<JSValue> Function()>>('jsUNDEFINED')
+ 149 : .asFunction();
+ 150 :
+ 151 : typedef _JSChannel = Pointer<JSValue> Function(
+ 152 : Pointer<JSContext> ctx, int method, Pointer<JSValue> argv);
+ 153 : typedef _JSChannelNative = Pointer<JSValue> Function(
+ 154 : Pointer<JSContext> ctx, IntPtr method, Pointer<JSValue> argv);
+ 155 :
+ 156 : /// JSRuntime *jsNewRuntime(JSChannel channel)
+ 157 : final Pointer<JSRuntime> Function(
+ 158 : Pointer<NativeFunction<_JSChannelNative>>,
+ 159 9 : ) _jsNewRuntime = _qjsLib
+ 160 3 : .lookup<
+ 161 : NativeFunction<
+ 162 : Pointer<JSRuntime> Function(
+ 163 : Pointer<NativeFunction<_JSChannelNative>>,
+ 164 : )>>('jsNewRuntime')
+ 165 : .asFunction();
+ 166 :
+ 167 : class _RuntimeOpaque {
+ 168 : final _JSChannel _channel;
+ 169 : List<JSRef> _ref = [];
+ 170 : final ReceivePort _port;
+ 171 : int? _dartObjectClassId;
+ 172 3 : _RuntimeOpaque(this._channel, this._port);
+ 173 :
+ 174 6 : int? get dartObjectClassId => _dartObjectClassId;
+ 175 :
+ 176 9 : void addRef(JSRef ref) => _ref.add(ref);
+ 177 :
+ 178 9 : bool removeRef(JSRef ref) => _ref.remove(ref);
+ 179 :
+ 180 3 : JSRef? getRef(bool Function(JSRef ref) test) {
+ 181 6 : return _ref.firstWhereOrNull(test);
+ 182 : }
+ 183 : }
+ 184 :
+ 185 9 : final Map<Pointer<JSRuntime>, _RuntimeOpaque> runtimeOpaques = Map();
+ 186 :
+ 187 3 : Pointer<JSValue>? channelDispacher(
+ 188 : Pointer<JSContext> ctx,
+ 189 : int type,
+ 190 : Pointer<JSValue> argv,
+ 191 : ) {
+ 192 3 : final rt = type == JSChannelType.FREE_OBJECT
+ 193 3 : ? ctx.cast<JSRuntime>()
+ 194 6 : : jsGetRuntime(ctx);
+ 195 12 : return runtimeOpaques[rt]?._channel(ctx, type, argv);
+ 196 : }
+ 197 :
+ 198 3 : Pointer<JSRuntime> jsNewRuntime(
+ 199 : _JSChannel callback,
+ 200 : ReceivePort port,
+ 201 : ) {
+ 202 6 : final rt = _jsNewRuntime(Pointer.fromFunction(channelDispacher));
+ 203 9 : runtimeOpaques[rt] = _RuntimeOpaque(callback, port);
+ 204 : return rt;
+ 205 : }
+ 206 :
+ 207 : /// DLLEXPORT void jsSetMaxStackSize(JSRuntime *rt, size_t stack_size)
+ 208 : final void Function(
+ 209 : Pointer<JSRuntime>,
+ 210 : int,
+ 211 0 : ) jsSetMaxStackSize = _qjsLib
+ 212 : .lookup<
+ 213 : NativeFunction<
+ 214 : Void Function(
+ 215 : Pointer<JSRuntime>,
+ 216 : IntPtr,
+ 217 : )>>('jsSetMaxStackSize')
+ 218 : .asFunction();
+ 219 :
+ 220 : /// void jsFreeRuntime(JSRuntime *rt)
+ 221 : final void Function(
+ 222 : Pointer<JSRuntime>,
+ 223 9 : ) _jsFreeRuntime = _qjsLib
+ 224 3 : .lookup<
+ 225 : NativeFunction<
+ 226 : Void Function(
+ 227 : Pointer<JSRuntime>,
+ 228 : )>>('jsFreeRuntime')
+ 229 : .asFunction();
+ 230 :
+ 231 3 : void jsFreeRuntime(
+ 232 : Pointer<JSRuntime> rt,
+ 233 : ) {
+ 234 3 : final referenceleak = <String>[];
+ 235 6 : final opaque = runtimeOpaques[rt];
+ 236 : if (opaque != null) {
+ 237 : while (true) {
+ 238 12 : final ref = opaque._ref.firstWhereOrNull((ref) => ref is JSRefLeakable);
+ 239 : if (ref == null) break;
+ 240 3 : ref.destroy();
+ 241 12 : runtimeOpaques[rt]?._ref.remove(ref);
+ 242 : }
+ 243 6 : while (opaque._ref.isNotEmpty) {
+ 244 2 : final ref = opaque._ref.first;
+ 245 2 : final objStrs = ref.toString().split('\n');
+ 246 4 : final objStr = objStrs.length > 0 ? objStrs[0] + " ..." : objStrs[0];
+ 247 1 : referenceleak.add(
+ 248 6 : " ${identityHashCode(ref)}\t${ref._refCount + 1}\t${ref.runtimeType.toString()}\t$objStr");
+ 249 1 : ref.destroy();
+ 250 : }
+ 251 : }
+ 252 6 : _jsFreeRuntime(rt);
+ 253 6 : if (referenceleak.length > 0) {
+ 254 1 : throw ('reference leak:\n ADDR\tREF\tTYPE\tPROP\n' +
+ 255 1 : referenceleak.join('\n'));
+ 256 : }
+ 257 : }
+ 258 :
+ 259 : /// JSValue *jsNewCFunction(JSContext *ctx, JSValue *funcData)
+ 260 : final Pointer<JSValue> Function(
+ 261 : Pointer<JSContext> ctx,
+ 262 : Pointer<JSValue> funcData,
+ 263 9 : ) jsNewCFunction = _qjsLib
+ 264 3 : .lookup<
+ 265 : NativeFunction<
+ 266 : Pointer<JSValue> Function(
+ 267 : Pointer<JSContext>,
+ 268 : Pointer<JSValue>,
+ 269 : )>>('jsNewCFunction')
+ 270 : .asFunction();
+ 271 :
+ 272 : /// JSContext *jsNewContext(JSRuntime *rt)
+ 273 : final Pointer<JSContext> Function(
+ 274 : Pointer<JSRuntime> rt,
+ 275 9 : ) _jsNewContext = _qjsLib
+ 276 3 : .lookup<
+ 277 : NativeFunction<
+ 278 : Pointer<JSContext> Function(
+ 279 : Pointer<JSRuntime>,
+ 280 : )>>('jsNewContext')
+ 281 : .asFunction();
+ 282 :
+ 283 3 : Pointer<JSContext> jsNewContext(Pointer<JSRuntime> rt) {
+ 284 6 : final ctx = _jsNewContext(rt);
+ 285 6 : final runtimeOpaque = runtimeOpaques[rt];
+ 286 0 : if (runtimeOpaque == null) throw Exception('Runtime has been released!');
+ 287 6 : runtimeOpaque._dartObjectClassId = jsNewClass(ctx, 'DartObject');
+ 288 : return ctx;
+ 289 : }
+ 290 :
+ 291 : /// void jsFreeContext(JSContext *ctx)
+ 292 : final void Function(
+ 293 : Pointer<JSContext>,
+ 294 9 : ) jsFreeContext = _qjsLib
+ 295 3 : .lookup<
+ 296 : NativeFunction<
+ 297 : Void Function(
+ 298 : Pointer<JSContext>,
+ 299 : )>>('jsFreeContext')
+ 300 : .asFunction();
+ 301 :
+ 302 : /// JSRuntime *jsGetRuntime(JSContext *ctx)
+ 303 : final Pointer<JSRuntime> Function(
+ 304 : Pointer<JSContext>,
+ 305 9 : ) jsGetRuntime = _qjsLib
+ 306 3 : .lookup<
+ 307 : NativeFunction<
+ 308 : Pointer<JSRuntime> Function(
+ 309 : Pointer<JSContext>,
+ 310 : )>>('jsGetRuntime')
+ 311 : .asFunction();
+ 312 :
+ 313 : /// JSValue *jsEval(JSContext *ctx, const char *input, size_t input_len, const char *filename, int eval_flags)
+ 314 : final Pointer<JSValue> Function(
+ 315 : Pointer<JSContext> ctx,
+ 316 : Pointer<Utf8> input,
+ 317 : int inputLen,
+ 318 : Pointer<Utf8> filename,
+ 319 : int evalFlags,
+ 320 9 : ) _jsEval = _qjsLib
+ 321 3 : .lookup<
+ 322 : NativeFunction<
+ 323 : Pointer<JSValue> Function(
+ 324 : Pointer<JSContext>,
+ 325 : Pointer<Utf8>,
+ 326 : IntPtr,
+ 327 : Pointer<Utf8>,
+ 328 : Int32,
+ 329 : )>>('jsEval')
+ 330 : .asFunction();
+ 331 :
+ 332 3 : Pointer<JSValue> jsEval(
+ 333 : Pointer<JSContext> ctx,
+ 334 : String input,
+ 335 : String filename,
+ 336 : int evalFlags,
+ 337 : ) {
+ 338 3 : final utf8input = input.toNativeUtf8();
+ 339 3 : final utf8filename = filename.toNativeUtf8();
+ 340 6 : final val = _jsEval(
+ 341 : ctx,
+ 342 : utf8input,
+ 343 3 : utf8input.length,
+ 344 : utf8filename,
+ 345 : evalFlags,
+ 346 : );
+ 347 3 : malloc.free(utf8input);
+ 348 3 : malloc.free(utf8filename);
+ 349 21 : runtimeOpaques[jsGetRuntime(ctx)]?._port.sendPort.send(#eval);
+ 350 : return val;
+ 351 : }
+ 352 :
+ 353 : /// DLLEXPORT int32_t jsValueGetTag(JSValue *val)
+ 354 : final int Function(
+ 355 : Pointer<JSValue> val,
+ 356 9 : ) jsValueGetTag = _qjsLib
+ 357 3 : .lookup<
+ 358 : NativeFunction<
+ 359 : Int32 Function(
+ 360 : Pointer<JSValue>,
+ 361 : )>>('jsValueGetTag')
+ 362 : .asFunction();
+ 363 :
+ 364 : /// void *jsValueGetPtr(JSValue *val)
+ 365 : final int Function(
+ 366 : Pointer<JSValue> val,
+ 367 9 : ) jsValueGetPtr = _qjsLib
+ 368 3 : .lookup<
+ 369 : NativeFunction<
+ 370 : IntPtr Function(
+ 371 : Pointer<JSValue>,
+ 372 : )>>('jsValueGetPtr')
+ 373 : .asFunction();
+ 374 :
+ 375 : /// DLLEXPORT bool jsTagIsFloat64(int32_t tag)
+ 376 : final int Function(
+ 377 : int val,
+ 378 9 : ) jsTagIsFloat64 = _qjsLib
+ 379 3 : .lookup<
+ 380 : NativeFunction<
+ 381 : Int32 Function(
+ 382 : Int32,
+ 383 : )>>('jsTagIsFloat64')
+ 384 : .asFunction();
+ 385 :
+ 386 : /// JSValue *jsNewBool(JSContext *ctx, int val)
+ 387 : final Pointer<JSValue> Function(
+ 388 : Pointer<JSContext> ctx,
+ 389 : int val,
+ 390 6 : ) jsNewBool = _qjsLib
+ 391 2 : .lookup<
+ 392 : NativeFunction<
+ 393 : Pointer<JSValue> Function(
+ 394 : Pointer<JSContext>,
+ 395 : Int32,
+ 396 : )>>('jsNewBool')
+ 397 : .asFunction();
+ 398 :
+ 399 : /// JSValue *jsNewInt64(JSContext *ctx, int64_t val)
+ 400 : final Pointer<JSValue> Function(
+ 401 : Pointer<JSContext> ctx,
+ 402 : int val,
+ 403 6 : ) jsNewInt64 = _qjsLib
+ 404 2 : .lookup<
+ 405 : NativeFunction<
+ 406 : Pointer<JSValue> Function(
+ 407 : Pointer<JSContext>,
+ 408 : Int64,
+ 409 : )>>('jsNewInt64')
+ 410 : .asFunction();
+ 411 :
+ 412 : /// JSValue *jsNewFloat64(JSContext *ctx, double val)
+ 413 : final Pointer<JSValue> Function(
+ 414 : Pointer<JSContext> ctx,
+ 415 : double val,
+ 416 6 : ) jsNewFloat64 = _qjsLib
+ 417 2 : .lookup<
+ 418 : NativeFunction<
+ 419 : Pointer<JSValue> Function(
+ 420 : Pointer<JSContext>,
+ 421 : Double,
+ 422 : )>>('jsNewFloat64')
+ 423 : .asFunction();
+ 424 :
+ 425 : /// JSValue *jsNewString(JSContext *ctx, const char *str)
+ 426 : final Pointer<JSValue> Function(
+ 427 : Pointer<JSContext> ctx,
+ 428 : Pointer<Utf8> str,
+ 429 9 : ) _jsNewString = _qjsLib
+ 430 3 : .lookup<
+ 431 : NativeFunction<
+ 432 : Pointer<JSValue> Function(
+ 433 : Pointer<JSContext>,
+ 434 : Pointer<Utf8>,
+ 435 : )>>('jsNewString')
+ 436 : .asFunction();
+ 437 :
+ 438 3 : Pointer<JSValue> jsNewString(
+ 439 : Pointer<JSContext> ctx,
+ 440 : String str,
+ 441 : ) {
+ 442 3 : final utf8str = str.toNativeUtf8();
+ 443 6 : final jsStr = _jsNewString(ctx, utf8str);
+ 444 3 : malloc.free(utf8str);
+ 445 : return jsStr;
+ 446 : }
+ 447 :
+ 448 : /// JSValue *jsNewArrayBufferCopy(JSContext *ctx, const uint8_t *buf, size_t len)
+ 449 : final Pointer<JSValue> Function(
+ 450 : Pointer<JSContext> ctx,
+ 451 : Pointer<Uint8> buf,
+ 452 : int len,
+ 453 0 : ) jsNewArrayBufferCopy = _qjsLib
+ 454 : .lookup<
+ 455 : NativeFunction<
+ 456 : Pointer<JSValue> Function(
+ 457 : Pointer<JSContext>,
+ 458 : Pointer<Uint8>,
+ 459 : IntPtr,
+ 460 : )>>('jsNewArrayBufferCopy')
+ 461 : .asFunction();
+ 462 :
+ 463 : /// JSValue *jsNewArray(JSContext *ctx)
+ 464 : final Pointer<JSValue> Function(
+ 465 : Pointer<JSContext> ctx,
+ 466 6 : ) jsNewArray = _qjsLib
+ 467 2 : .lookup<
+ 468 : NativeFunction<
+ 469 : Pointer<JSValue> Function(
+ 470 : Pointer<JSContext>,
+ 471 : )>>('jsNewArray')
+ 472 : .asFunction();
+ 473 :
+ 474 : /// JSValue *jsNewObject(JSContext *ctx)
+ 475 : final Pointer<JSValue> Function(
+ 476 : Pointer<JSContext> ctx,
+ 477 6 : ) jsNewObject = _qjsLib
+ 478 2 : .lookup<
+ 479 : NativeFunction<
+ 480 : Pointer<JSValue> Function(
+ 481 : Pointer<JSContext>,
+ 482 : )>>('jsNewObject')
+ 483 : .asFunction();
+ 484 :
+ 485 : /// void jsFreeValue(JSContext *ctx, JSValue *val, int32_t free)
+ 486 : final void Function(
+ 487 : Pointer<JSContext> ctx,
+ 488 : Pointer<JSValue> val,
+ 489 : int free,
+ 490 9 : ) _jsFreeValue = _qjsLib
+ 491 3 : .lookup<
+ 492 : NativeFunction<
+ 493 : Void Function(
+ 494 : Pointer<JSContext>,
+ 495 : Pointer<JSValue>,
+ 496 : Int32,
+ 497 : )>>('jsFreeValue')
+ 498 : .asFunction();
+ 499 :
+ 500 3 : void jsFreeValue(
+ 501 : Pointer<JSContext> ctx,
+ 502 : Pointer<JSValue> val, {
+ 503 : bool free = true,
+ 504 : }) {
+ 505 6 : _jsFreeValue(ctx, val, free ? 1 : 0);
+ 506 : }
+ 507 :
+ 508 : /// void jsFreeValue(JSRuntime *rt, JSValue *val, int32_t free)
+ 509 : final void Function(
+ 510 : Pointer<JSRuntime> rt,
+ 511 : Pointer<JSValue> val,
+ 512 : int free,
+ 513 0 : ) _jsFreeValueRT = _qjsLib
+ 514 : .lookup<
+ 515 : NativeFunction<
+ 516 : Void Function(
+ 517 : Pointer<JSRuntime>,
+ 518 : Pointer<JSValue>,
+ 519 : Int32,
+ 520 : )>>('jsFreeValueRT')
+ 521 : .asFunction();
+ 522 :
+ 523 0 : void jsFreeValueRT(
+ 524 : Pointer<JSRuntime> rt,
+ 525 : Pointer<JSValue> val, {
+ 526 : bool free = true,
+ 527 : }) {
+ 528 0 : _jsFreeValueRT(rt, val, free ? 1 : 0);
+ 529 : }
+ 530 :
+ 531 : /// JSValue *jsDupValue(JSContext *ctx, JSValueConst *v)
+ 532 : final Pointer<JSValue> Function(
+ 533 : Pointer<JSContext> ctx,
+ 534 : Pointer<JSValue> val,
+ 535 9 : ) jsDupValue = _qjsLib
+ 536 3 : .lookup<
+ 537 : NativeFunction<
+ 538 : Pointer<JSValue> Function(
+ 539 : Pointer<JSContext>,
+ 540 : Pointer<JSValue>,
+ 541 : )>>('jsDupValue')
+ 542 : .asFunction();
+ 543 :
+ 544 : /// JSValue *jsDupValueRT(JSRuntime *rt, JSValue *v)
+ 545 : final Pointer<JSValue> Function(
+ 546 : Pointer<JSRuntime> rt,
+ 547 : Pointer<JSValue> val,
+ 548 0 : ) jsDupValueRT = _qjsLib
+ 549 : .lookup<
+ 550 : NativeFunction<
+ 551 : Pointer<JSValue> Function(
+ 552 : Pointer<JSRuntime>,
+ 553 : Pointer<JSValue>,
+ 554 : )>>('jsDupValueRT')
+ 555 : .asFunction();
+ 556 :
+ 557 : /// int32_t jsToBool(JSContext *ctx, JSValueConst *val)
+ 558 : final int Function(
+ 559 : Pointer<JSContext> ctx,
+ 560 : Pointer<JSValue> val,
+ 561 6 : ) jsToBool = _qjsLib
+ 562 2 : .lookup<
+ 563 : NativeFunction<
+ 564 : Int32 Function(
+ 565 : Pointer<JSContext>,
+ 566 : Pointer<JSValue>,
+ 567 : )>>('jsToBool')
+ 568 : .asFunction();
+ 569 :
+ 570 : /// int64_t jsToFloat64(JSContext *ctx, JSValueConst *val)
+ 571 : final int Function(
+ 572 : Pointer<JSContext> ctx,
+ 573 : Pointer<JSValue> val,
+ 574 6 : ) jsToInt64 = _qjsLib
+ 575 2 : .lookup<
+ 576 : NativeFunction<
+ 577 : Int64 Function(
+ 578 : Pointer<JSContext>,
+ 579 : Pointer<JSValue>,
+ 580 : )>>('jsToInt64')
+ 581 : .asFunction();
+ 582 :
+ 583 : /// double jsToFloat64(JSContext *ctx, JSValueConst *val)
+ 584 : final double Function(
+ 585 : Pointer<JSContext> ctx,
+ 586 : Pointer<JSValue> val,
+ 587 6 : ) jsToFloat64 = _qjsLib
+ 588 2 : .lookup<
+ 589 : NativeFunction<
+ 590 : Double Function(
+ 591 : Pointer<JSContext>,
+ 592 : Pointer<JSValue>,
+ 593 : )>>('jsToFloat64')
+ 594 : .asFunction();
+ 595 :
+ 596 : /// const char *jsToCString(JSContext *ctx, JSValue *val)
+ 597 : final Pointer<Utf8> Function(
+ 598 : Pointer<JSContext> ctx,
+ 599 : Pointer<JSValue> val,
+ 600 9 : ) _jsToCString = _qjsLib
+ 601 3 : .lookup<
+ 602 : NativeFunction<
+ 603 : Pointer<Utf8> Function(
+ 604 : Pointer<JSContext>,
+ 605 : Pointer<JSValue>,
+ 606 : )>>('jsToCString')
+ 607 : .asFunction();
+ 608 :
+ 609 : /// void jsFreeCString(JSContext *ctx, const char *ptr)
+ 610 : final void Function(
+ 611 : Pointer<JSContext> ctx,
+ 612 : Pointer<Utf8> val,
+ 613 9 : ) jsFreeCString = _qjsLib
+ 614 3 : .lookup<
+ 615 : NativeFunction<
+ 616 : Void Function(
+ 617 : Pointer<JSContext>,
+ 618 : Pointer<Utf8>,
+ 619 : )>>('jsFreeCString')
+ 620 : .asFunction();
+ 621 :
+ 622 3 : String jsToCString(
+ 623 : Pointer<JSContext> ctx,
+ 624 : Pointer<JSValue> val,
+ 625 : ) {
+ 626 6 : final ptr = _jsToCString(ctx, val);
+ 627 6 : if (ptr.address == 0) throw Exception('JSValue cannot convert to string');
+ 628 3 : final str = ptr.toDartString();
+ 629 6 : jsFreeCString(ctx, ptr);
+ 630 : return str;
+ 631 : }
+ 632 :
+ 633 : /// DLLEXPORT uint32_t jsNewClass(JSContext *ctx, const char *name)
+ 634 : final int Function(
+ 635 : Pointer<JSContext> ctx,
+ 636 : Pointer<Utf8> name,
+ 637 9 : ) _jsNewClass = _qjsLib
+ 638 3 : .lookup<
+ 639 : NativeFunction<
+ 640 : Uint32 Function(
+ 641 : Pointer<JSContext>,
+ 642 : Pointer<Utf8>,
+ 643 : )>>('jsNewClass')
+ 644 : .asFunction();
+ 645 :
+ 646 3 : int jsNewClass(
+ 647 : Pointer<JSContext> ctx,
+ 648 : String name,
+ 649 : ) {
+ 650 3 : final utf8name = name.toNativeUtf8();
+ 651 6 : final val = _jsNewClass(
+ 652 : ctx,
+ 653 : utf8name,
+ 654 : );
+ 655 3 : malloc.free(utf8name);
+ 656 : return val;
+ 657 : }
+ 658 :
+ 659 : /// DLLEXPORT JSValue *jsNewObjectClass(JSContext *ctx, uint32_t QJSClassId, void *opaque)
+ 660 : final Pointer<JSValue> Function(
+ 661 : Pointer<JSContext> ctx,
+ 662 : int classId,
+ 663 : int opaque,
+ 664 9 : ) jsNewObjectClass = _qjsLib
+ 665 3 : .lookup<
+ 666 : NativeFunction<
+ 667 : Pointer<JSValue> Function(
+ 668 : Pointer<JSContext>,
+ 669 : Uint32,
+ 670 : IntPtr,
+ 671 : )>>('jsNewObjectClass')
+ 672 : .asFunction();
+ 673 :
+ 674 : /// DLLEXPORT void *jsGetObjectOpaque(JSValue *obj, uint32_t classid)
+ 675 : final int Function(
+ 676 : Pointer<JSValue> obj,
+ 677 : int classid,
+ 678 9 : ) jsGetObjectOpaque = _qjsLib
+ 679 3 : .lookup<
+ 680 : NativeFunction<
+ 681 : IntPtr Function(
+ 682 : Pointer<JSValue>,
+ 683 : Uint32,
+ 684 : )>>('jsGetObjectOpaque')
+ 685 : .asFunction();
+ 686 :
+ 687 : /// uint8_t *jsGetArrayBuffer(JSContext *ctx, size_t *psize, JSValueConst *obj)
+ 688 : final Pointer<Uint8> Function(
+ 689 : Pointer<JSContext> ctx,
+ 690 : Pointer<IntPtr> psize,
+ 691 : Pointer<JSValue> val,
+ 692 9 : ) jsGetArrayBuffer = _qjsLib
+ 693 3 : .lookup<
+ 694 : NativeFunction<
+ 695 : Pointer<Uint8> Function(
+ 696 : Pointer<JSContext>,
+ 697 : Pointer<IntPtr>,
+ 698 : Pointer<JSValue>,
+ 699 : )>>('jsGetArrayBuffer')
+ 700 : .asFunction();
+ 701 :
+ 702 : /// int32_t jsIsFunction(JSContext *ctx, JSValueConst *val)
+ 703 : final int Function(
+ 704 : Pointer<JSContext> ctx,
+ 705 : Pointer<JSValue> val,
+ 706 9 : ) jsIsFunction = _qjsLib
+ 707 3 : .lookup<
+ 708 : NativeFunction<
+ 709 : Int32 Function(
+ 710 : Pointer<JSContext>,
+ 711 : Pointer<JSValue>,
+ 712 : )>>('jsIsFunction')
+ 713 : .asFunction();
+ 714 :
+ 715 : /// int32_t jsIsPromise(JSContext *ctx, JSValueConst *val)
+ 716 : final int Function(
+ 717 : Pointer<JSContext> ctx,
+ 718 : Pointer<JSValue> val,
+ 719 9 : ) jsIsPromise = _qjsLib
+ 720 3 : .lookup<
+ 721 : NativeFunction<
+ 722 : Int32 Function(
+ 723 : Pointer<JSContext>,
+ 724 : Pointer<JSValue>,
+ 725 : )>>('jsIsPromise')
+ 726 : .asFunction();
+ 727 :
+ 728 : /// int32_t jsIsArray(JSContext *ctx, JSValueConst *val)
+ 729 : final int Function(
+ 730 : Pointer<JSContext> ctx,
+ 731 : Pointer<JSValue> val,
+ 732 6 : ) jsIsArray = _qjsLib
+ 733 2 : .lookup<
+ 734 : NativeFunction<
+ 735 : Int32 Function(
+ 736 : Pointer<JSContext>,
+ 737 : Pointer<JSValue>,
+ 738 : )>>('jsIsArray')
+ 739 : .asFunction();
+ 740 :
+ 741 : /// DLLEXPORT int32_t jsIsError(JSContext *ctx, JSValueConst *val);
+ 742 : final int Function(
+ 743 : Pointer<JSContext> ctx,
+ 744 : Pointer<JSValue> val,
+ 745 9 : ) jsIsError = _qjsLib
+ 746 3 : .lookup<
+ 747 : NativeFunction<
+ 748 : Int32 Function(
+ 749 : Pointer<JSContext>,
+ 750 : Pointer<JSValue>,
+ 751 : )>>('jsIsError')
+ 752 : .asFunction();
+ 753 :
+ 754 : /// DLLEXPORT JSValue *jsNewError(JSContext *ctx);
+ 755 : final Pointer<JSValue> Function(
+ 756 : Pointer<JSContext> ctx,
+ 757 6 : ) jsNewError = _qjsLib
+ 758 2 : .lookup<
+ 759 : NativeFunction<
+ 760 : Pointer<JSValue> Function(
+ 761 : Pointer<JSContext>,
+ 762 : )>>('jsNewError')
+ 763 : .asFunction();
+ 764 :
+ 765 : /// JSValue *jsGetProperty(JSContext *ctx, JSValueConst *this_obj,
+ 766 : /// JSAtom prop)
+ 767 : final Pointer<JSValue> Function(
+ 768 : Pointer<JSContext> ctx,
+ 769 : Pointer<JSValue> thisObj,
+ 770 : int prop,
+ 771 9 : ) jsGetProperty = _qjsLib
+ 772 3 : .lookup<
+ 773 : NativeFunction<
+ 774 : Pointer<JSValue> Function(
+ 775 : Pointer<JSContext>,
+ 776 : Pointer<JSValue>,
+ 777 : Uint32,
+ 778 : )>>('jsGetProperty')
+ 779 : .asFunction();
+ 780 :
+ 781 : /// int jsDefinePropertyValue(JSContext *ctx, JSValueConst *this_obj,
+ 782 : /// JSAtom prop, JSValue *val, int flags)
+ 783 : final int Function(
+ 784 : Pointer<JSContext> ctx,
+ 785 : Pointer<JSValue> thisObj,
+ 786 : int prop,
+ 787 : Pointer<JSValue> val,
+ 788 : int flag,
+ 789 6 : ) jsDefinePropertyValue = _qjsLib
+ 790 2 : .lookup<
+ 791 : NativeFunction<
+ 792 : Int32 Function(
+ 793 : Pointer<JSContext>,
+ 794 : Pointer<JSValue>,
+ 795 : Uint32,
+ 796 : Pointer<JSValue>,
+ 797 : Int32,
+ 798 : )>>('jsDefinePropertyValue')
+ 799 : .asFunction();
+ 800 :
+ 801 : /// void jsFreeAtom(JSContext *ctx, JSAtom v)
+ 802 : final void Function(
+ 803 : Pointer<JSContext> ctx,
+ 804 : int v,
+ 805 9 : ) jsFreeAtom = _qjsLib
+ 806 3 : .lookup<
+ 807 : NativeFunction<
+ 808 : Void Function(
+ 809 : Pointer<JSContext>,
+ 810 : Uint32,
+ 811 : )>>('jsFreeAtom')
+ 812 : .asFunction();
+ 813 :
+ 814 : /// JSAtom jsValueToAtom(JSContext *ctx, JSValueConst *val)
+ 815 : final int Function(
+ 816 : Pointer<JSContext> ctx,
+ 817 : Pointer<JSValue> val,
+ 818 9 : ) jsValueToAtom = _qjsLib
+ 819 3 : .lookup<
+ 820 : NativeFunction<
+ 821 : Uint32 Function(
+ 822 : Pointer<JSContext>,
+ 823 : Pointer<JSValue>,
+ 824 : )>>('jsValueToAtom')
+ 825 : .asFunction();
+ 826 :
+ 827 : /// JSValue *jsAtomToValue(JSContext *ctx, JSAtom val)
+ 828 : final Pointer<JSValue> Function(
+ 829 : Pointer<JSContext> ctx,
+ 830 : int val,
+ 831 6 : ) jsAtomToValue = _qjsLib
+ 832 2 : .lookup<
+ 833 : NativeFunction<
+ 834 : Pointer<JSValue> Function(
+ 835 : Pointer<JSContext>,
+ 836 : Uint32,
+ 837 : )>>('jsAtomToValue')
+ 838 : .asFunction();
+ 839 :
+ 840 : /// int jsGetOwnPropertyNames(JSContext *ctx, JSPropertyEnum **ptab,
+ 841 : /// uint32_t *plen, JSValueConst *obj, int flags)
+ 842 : final int Function(
+ 843 : Pointer<JSContext> ctx,
+ 844 : Pointer<Pointer<JSPropertyEnum>> ptab,
+ 845 : Pointer<Uint32> plen,
+ 846 : Pointer<JSValue> obj,
+ 847 : int flags,
+ 848 6 : ) jsGetOwnPropertyNames = _qjsLib
+ 849 2 : .lookup<
+ 850 : NativeFunction<
+ 851 : Int32 Function(
+ 852 : Pointer<JSContext>,
+ 853 : Pointer<Pointer<JSPropertyEnum>>,
+ 854 : Pointer<Uint32>,
+ 855 : Pointer<JSValue>,
+ 856 : Int32,
+ 857 : )>>('jsGetOwnPropertyNames')
+ 858 : .asFunction();
+ 859 :
+ 860 : /// JSAtom jsPropertyEnumGetAtom(JSPropertyEnum *ptab, int i)
+ 861 : final int Function(
+ 862 : Pointer<JSPropertyEnum> ptab,
+ 863 : int i,
+ 864 6 : ) jsPropertyEnumGetAtom = _qjsLib
+ 865 2 : .lookup<
+ 866 : NativeFunction<
+ 867 : Uint32 Function(
+ 868 : Pointer<JSPropertyEnum>,
+ 869 : Int32,
+ 870 : )>>('jsPropertyEnumGetAtom')
+ 871 : .asFunction();
+ 872 :
+ 873 : /// uint32_t sizeOfJSValue()
+ 874 9 : final int Function() _sizeOfJSValue = _qjsLib
+ 875 3 : .lookup<NativeFunction<Uint32 Function()>>('sizeOfJSValue')
+ 876 : .asFunction();
+ 877 :
+ 878 12 : final sizeOfJSValue = _sizeOfJSValue();
+ 879 :
+ 880 : /// void setJSValueList(JSValue *list, int i, JSValue *val)
+ 881 : final void Function(
+ 882 : Pointer<JSValue> list,
+ 883 : int i,
+ 884 : Pointer<JSValue> val,
+ 885 9 : ) setJSValueList = _qjsLib
+ 886 3 : .lookup<
+ 887 : NativeFunction<
+ 888 : Void Function(
+ 889 : Pointer<JSValue>,
+ 890 : Uint32,
+ 891 : Pointer<JSValue>,
+ 892 : )>>('setJSValueList')
+ 893 : .asFunction();
+ 894 :
+ 895 : /// JSValue *jsCall(JSContext *ctx, JSValueConst *func_obj, JSValueConst *this_obj,
+ 896 : /// int argc, JSValueConst *argv)
+ 897 : final Pointer<JSValue> Function(
+ 898 : Pointer<JSContext> ctx,
+ 899 : Pointer<JSValue> funcObj,
+ 900 : Pointer<JSValue> thisObj,
+ 901 : int argc,
+ 902 : Pointer<JSValue> argv,
+ 903 9 : ) _jsCall = _qjsLib
+ 904 3 : .lookup<
+ 905 : NativeFunction<
+ 906 : Pointer<JSValue> Function(
+ 907 : Pointer<JSContext>,
+ 908 : Pointer<JSValue>,
+ 909 : Pointer<JSValue>,
+ 910 : Int32,
+ 911 : Pointer<JSValue>,
+ 912 : )>>('jsCall')
+ 913 : .asFunction();
+ 914 :
+ 915 3 : Pointer<JSValue> jsCall(
+ 916 : Pointer<JSContext> ctx,
+ 917 : Pointer<JSValue> funcObj,
+ 918 : Pointer<JSValue> thisObj,
+ 919 : List<Pointer<JSValue>> argv,
+ 920 : ) {
+ 921 : final jsArgs = calloc<Uint8>(
+ 922 15 : argv.length > 0 ? sizeOfJSValue * argv.length : 1,
+ 923 3 : ).cast<JSValue>();
+ 924 9 : for (int i = 0; i < argv.length; ++i) {
+ 925 3 : Pointer<JSValue> jsArg = argv[i];
+ 926 6 : setJSValueList(jsArgs, i, jsArg);
+ 927 : }
+ 928 6 : final func1 = jsDupValue(ctx, funcObj);
+ 929 : final _thisObj = thisObj;
+ 930 9 : final jsRet = _jsCall(ctx, funcObj, _thisObj, argv.length, jsArgs);
+ 931 3 : jsFreeValue(ctx, func1);
+ 932 3 : malloc.free(jsArgs);
+ 933 21 : runtimeOpaques[jsGetRuntime(ctx)]?._port.sendPort.send(#call);
+ 934 : return jsRet;
+ 935 : }
+ 936 :
+ 937 : /// int jsIsException(JSValueConst *val)
+ 938 : final int Function(
+ 939 : Pointer<JSValue> val,
+ 940 9 : ) jsIsException = _qjsLib
+ 941 3 : .lookup<
+ 942 : NativeFunction<
+ 943 : Int32 Function(
+ 944 : Pointer<JSValue>,
+ 945 : )>>('jsIsException')
+ 946 : .asFunction();
+ 947 :
+ 948 : /// JSValue *jsGetException(JSContext *ctx)
+ 949 : final Pointer<JSValue> Function(
+ 950 : Pointer<JSContext> ctx,
+ 951 3 : ) jsGetException = _qjsLib
+ 952 1 : .lookup<
+ 953 : NativeFunction<
+ 954 : Pointer<JSValue> Function(
+ 955 : Pointer<JSContext>,
+ 956 : )>>('jsGetException')
+ 957 : .asFunction();
+ 958 :
+ 959 : /// int jsExecutePendingJob(JSRuntime *rt)
+ 960 : final int Function(
+ 961 : Pointer<JSRuntime> ctx,
+ 962 9 : ) jsExecutePendingJob = _qjsLib
+ 963 3 : .lookup<
+ 964 : NativeFunction<
+ 965 : Int32 Function(
+ 966 : Pointer<JSRuntime>,
+ 967 : )>>('jsExecutePendingJob')
+ 968 : .asFunction();
+ 969 :
+ 970 : /// JSValue *jsNewPromiseCapability(JSContext *ctx, JSValue *resolving_funcs)
+ 971 : final Pointer<JSValue> Function(
+ 972 : Pointer<JSContext> ctx,
+ 973 : Pointer<JSValue> resolvingFuncs,
+ 974 9 : ) jsNewPromiseCapability = _qjsLib
+ 975 3 : .lookup<
+ 976 : NativeFunction<
+ 977 : Pointer<JSValue> Function(
+ 978 : Pointer<JSContext>,
+ 979 : Pointer<JSValue>,
+ 980 : )>>('jsNewPromiseCapability')
+ 981 : .asFunction();
+ 982 :
+ 983 : /// void jsFree(JSContext *ctx, void *ptab)
+ 984 : final void Function(
+ 985 : Pointer<JSContext> ctx,
+ 986 : Pointer<JSPropertyEnum> ptab,
+ 987 6 : ) jsFree = _qjsLib
+ 988 2 : .lookup<
+ 989 : NativeFunction<
+ 990 : Void Function(
+ 991 : Pointer<JSContext>,
+ 992 : Pointer<JSPropertyEnum>,
+ 993 : )>>('jsFree')
+ 994 : .asFunction();
+
+ |
+
+