LCOV - code coverage report
Current view: top level - src - ffi.dart (source / functions) Hit Total Coverage
Test: lcov.info Lines: 192 209 91.9 %
Date: 2021-03-31 22:28:15 Functions: 0 0 -

          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();

Generated by: LCOV version 1.14