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