From d059ac01fdfb00626703007f41f73c869c630b53 Mon Sep 17 00:00:00 2001 From: Mario Zechner Date: Wed, 30 Jul 2025 23:41:36 +0200 Subject: [PATCH] [flutter] Switch to wasm_ffi --- spine-flutter/codegen/src/dart-writer.ts | 32 +- spine-flutter/example/pubspec.lock | 30 +- spine-flutter/lib/ffi_proxy.dart | 7 +- spine-flutter/lib/malloc_web.dart | 16 +- spine-flutter/lib/spine_dart_init_web.dart | 28 +- spine-flutter/lib/web_ffi/ffi/extensions.dart | 253 ---- spine-flutter/lib/web_ffi/ffi/types.dart | 418 ------- spine-flutter/lib/web_ffi/ffi/utf8.dart | 89 -- .../web_ffi/internal/invoker_generated.dart | 1089 ----------------- .../lib/web_ffi/internal/marshaller.dart | 278 ----- .../lib/web_ffi/internal/type_utils.dart | 55 - spine-flutter/lib/web_ffi/meta/meta.dart | 35 - .../modules/emscripten/emscripten_module.dart | 186 --- .../emscripten/emscripten_module_stub.dart | 68 - .../lib/web_ffi/modules/exceptions.dart | 17 - spine-flutter/lib/web_ffi/modules/memory.dart | 123 -- spine-flutter/lib/web_ffi/modules/module.dart | 107 -- .../lib/web_ffi/modules/null_memory.dart | 18 - spine-flutter/lib/web_ffi/web_ffi.dart | 7 - spine-flutter/lib/web_ffi/web_ffi_meta.dart | 4 - .../lib/web_ffi/web_ffi_modules.dart | 10 - spine-flutter/pubspec.yaml | 1 + spine-flutter/test/pubspec.lock | 10 +- 23 files changed, 61 insertions(+), 2820 deletions(-) delete mode 100755 spine-flutter/lib/web_ffi/ffi/extensions.dart delete mode 100755 spine-flutter/lib/web_ffi/ffi/types.dart delete mode 100644 spine-flutter/lib/web_ffi/ffi/utf8.dart delete mode 100755 spine-flutter/lib/web_ffi/internal/invoker_generated.dart delete mode 100755 spine-flutter/lib/web_ffi/internal/marshaller.dart delete mode 100755 spine-flutter/lib/web_ffi/internal/type_utils.dart delete mode 100755 spine-flutter/lib/web_ffi/meta/meta.dart delete mode 100755 spine-flutter/lib/web_ffi/modules/emscripten/emscripten_module.dart delete mode 100755 spine-flutter/lib/web_ffi/modules/emscripten/emscripten_module_stub.dart delete mode 100755 spine-flutter/lib/web_ffi/modules/exceptions.dart delete mode 100755 spine-flutter/lib/web_ffi/modules/memory.dart delete mode 100755 spine-flutter/lib/web_ffi/modules/module.dart delete mode 100755 spine-flutter/lib/web_ffi/modules/null_memory.dart delete mode 100755 spine-flutter/lib/web_ffi/web_ffi.dart delete mode 100755 spine-flutter/lib/web_ffi/web_ffi_meta.dart delete mode 100755 spine-flutter/lib/web_ffi/web_ffi_modules.dart diff --git a/spine-flutter/codegen/src/dart-writer.ts b/spine-flutter/codegen/src/dart-writer.ts index 2ea30ca93..e91d9461e 100644 --- a/spine-flutter/codegen/src/dart-writer.ts +++ b/spine-flutter/codegen/src/dart-writer.ts @@ -1610,13 +1610,12 @@ ${declaration} {`; lines.push(''); lines.push('// ignore_for_file: type_argument_not_matching_bounds'); lines.push(`import 'package:flutter/services.dart';`); - lines.push(`import 'package:inject_js/inject_js.dart' as js;`); - lines.push(`import 'web_ffi/web_ffi.dart';`); - lines.push(`import 'web_ffi/web_ffi_modules.dart';`); + lines.push(`import 'package:wasm_ffi/ffi.dart';`); lines.push(''); lines.push(`import 'generated/spine_dart_bindings_generated.dart';`); lines.push(''); - lines.push('Module? _module;'); + lines.push('// Export this so malloc_web.dart can access it'); + lines.push('DynamicLibrary? dylibInstance;'); lines.push(''); lines.push('class SpineDartFFI {'); lines.push(' final DynamicLibrary dylib;'); @@ -1626,8 +1625,7 @@ ${declaration} {`; lines.push('}'); lines.push(''); lines.push('Future initSpineDartFFI(bool useStaticLinkage) async {'); - lines.push(' if (_module == null) {'); - lines.push(' Memory.init();'); + lines.push(' if (dylibInstance == null) {'); lines.push(''); // Collect all wrapper types @@ -1652,25 +1650,21 @@ ${declaration} {`; wrapperTypes.add('spine_skin_entries_wrapper'); wrapperTypes.add('spine_texture_loader_wrapper'); + lines.push(''); + lines.push(` // Load the wasm module first - this calls initTypes()`); + lines.push(` dylibInstance = await DynamicLibrary.open('assets/packages/spine_flutter/lib/assets/libspine_flutter.js');`); + lines.push(''); + lines.push(' // Now register all the opaque types'); + // Sort and write all registerOpaqueType calls const sortedTypes = Array.from(wrapperTypes).sort(); for (const type of sortedTypes) { lines.push(` registerOpaqueType<${type}>();`); } - - lines.push(''); - lines.push(` await js.importLibrary('assets/packages/spine_flutter/lib/assets/libspine_flutter.js');`); - lines.push(` Uint8List wasmBinaries = (await rootBundle.load(`); - lines.push(` 'packages/spine_flutter/lib/assets/libspine_flutter.wasm',`); - lines.push(` ))`); - lines.push(` .buffer`); - lines.push(` .asUint8List();`); - lines.push(` _module = await EmscriptenModule.compile(wasmBinaries, 'libspine_flutter');`); lines.push(' }'); - lines.push(' Module? m = _module;'); - lines.push(' if (m != null) {'); - lines.push(' final dylib = DynamicLibrary.fromModule(m);'); - lines.push(' return SpineDartFFI(dylib, dylib.boundMemory);'); + lines.push(' '); + lines.push(' if (dylibInstance != null) {'); + lines.push(' return SpineDartFFI(dylibInstance!, dylibInstance!.allocator);'); lines.push(' } else {'); lines.push(` throw Exception("Couldn't load libspine-flutter.js/.wasm");`); lines.push(' }'); diff --git a/spine-flutter/example/pubspec.lock b/spine-flutter/example/pubspec.lock index dc1bdaa9e..69991c882 100644 --- a/spine-flutter/example/pubspec.lock +++ b/spine-flutter/example/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: ffi - sha256: "7bf0adc28a23d395f19f3f1eb21dd7cfd1dd9f8e1c50051c069122e6853bc878" + sha256: "289279317b4b16eb2bb7e271abccd4bf84ec9bdcbe999e278a94b804f5630418" url: "https://pub.dev" source: hosted - version: "2.1.0" + version: "2.1.4" flame: dependency: "direct main" description: @@ -74,10 +74,10 @@ packages: dependency: transitive description: name: http - sha256: "759d1a329847dd0f39226c688d3e06a6b8679668e350e2891a6474f8b4bb8525" + sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b" url: "https://pub.dev" source: hosted - version: "1.1.0" + version: "1.4.0" http_parser: dependency: transitive description: @@ -138,10 +138,10 @@ packages: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "75cca69d1490965be98c73ceaea117e8a04dd21217b37b292c9ddbec0d955bc5" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.1" raw_image_provider: dependency: "direct main" description: @@ -202,6 +202,22 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" + wasm_ffi: + dependency: transitive + description: + name: wasm_ffi + sha256: f4539052e4d80575bb4820c836a2d6400af061b71c1605af60ebfb30b7c5369a + url: "https://pub.dev" + source: hosted + version: "2.0.7" + web: + dependency: transitive + description: + name: web + sha256: "868d88a33d8a87b18ffc05f9f030ba328ffefba92d6c127917a2ba740f9cfe4a" + url: "https://pub.dev" + source: hosted + version: "1.1.1" sdks: - dart: ">=3.7.0-0 <4.0.0" + dart: ">=3.7.0 <4.0.0" flutter: ">=3.27.1" diff --git a/spine-flutter/lib/ffi_proxy.dart b/spine-flutter/lib/ffi_proxy.dart index ac708e0b8..425c01f7b 100644 --- a/spine-flutter/lib/ffi_proxy.dart +++ b/spine-flutter/lib/ffi_proxy.dart @@ -27,7 +27,8 @@ /// THE SPINE RUNTIMES, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. /// -export 'dart:ffi' if (dart.library.html) 'web_ffi/web_ffi.dart'; +export 'dart:ffi' if (dart.library.html) 'package:wasm_ffi/ffi.dart'; -export 'package:ffi/ffi.dart' if (dart.library.html) 'web_ffi/ffi/utf8.dart'; -export 'malloc_native.dart' if (dart.library.html) 'malloc_web.dart'; +export 'package:ffi/ffi.dart' if (dart.library.html) 'package:wasm_ffi/ffi_utils.dart'; +// Only export our custom malloc on native platforms +export 'malloc_native.dart' if (dart.library.io) 'malloc_native.dart'; diff --git a/spine-flutter/lib/malloc_web.dart b/spine-flutter/lib/malloc_web.dart index 8efaf35cd..30b68fdb5 100644 --- a/spine-flutter/lib/malloc_web.dart +++ b/spine-flutter/lib/malloc_web.dart @@ -1,11 +1,13 @@ -import 'web_ffi/web_ffi.dart'; -import 'web_ffi/web_ffi_modules.dart'; +import 'package:wasm_ffi/ffi.dart'; +import 'spine_dart_init_web.dart'; -/// Web implementation of malloc that uses the Memory allocator -/// Memory.global will be set when the DynamicLibrary is loaded +/// Web implementation of malloc that uses the DynamicLibrary's allocator +/// The allocator will be available after spine is initialized Allocator get malloc { - if (Memory.global == null) { - throw StateError('Memory.global is not initialized. Make sure spine is initialized before using malloc.'); + // Get the allocator from the current dylib + final dylib = dylibInstance; + if (dylib == null) { + throw StateError('DynamicLibrary is not initialized. Make sure spine is initialized before using malloc.'); } - return Memory.global!; + return dylib.allocator; } diff --git a/spine-flutter/lib/spine_dart_init_web.dart b/spine-flutter/lib/spine_dart_init_web.dart index 3382796c2..b05b9e2cb 100644 --- a/spine-flutter/lib/spine_dart_init_web.dart +++ b/spine-flutter/lib/spine_dart_init_web.dart @@ -31,13 +31,12 @@ // ignore_for_file: type_argument_not_matching_bounds import 'package:flutter/services.dart'; -import 'package:inject_js/inject_js.dart' as js; -import 'web_ffi/web_ffi.dart'; -import 'web_ffi/web_ffi_modules.dart'; +import 'package:wasm_ffi/ffi.dart'; import 'generated/spine_dart_bindings_generated.dart'; -Module? _module; +// Export this so malloc_web.dart can access it +DynamicLibrary? dylibInstance; class SpineDartFFI { final DynamicLibrary dylib; @@ -47,9 +46,11 @@ class SpineDartFFI { } Future initSpineDartFFI(bool useStaticLinkage) async { - if (_module == null) { - Memory.init(); + if (dylibInstance == null) { + // Load the wasm module first - this calls initTypes() + dylibInstance = await DynamicLibrary.open('assets/packages/spine_flutter/lib/assets/libspine_flutter.js'); + // Now register all the opaque types registerOpaqueType(); registerOpaqueType(); registerOpaqueType(); @@ -208,19 +209,10 @@ Future initSpineDartFFI(bool useStaticLinkage) async { registerOpaqueType(); registerOpaqueType(); registerOpaqueType(); - - await js.importLibrary('assets/packages/spine_flutter/lib/assets/libspine_flutter.js'); - Uint8List wasmBinaries = (await rootBundle.load( - 'packages/spine_flutter/lib/assets/libspine_flutter.wasm', - )) - .buffer - .asUint8List(); - _module = await EmscriptenModule.compile(wasmBinaries, 'libspine_flutter'); } - Module? m = _module; - if (m != null) { - final dylib = DynamicLibrary.fromModule(m); - return SpineDartFFI(dylib, dylib.boundMemory); + + if (dylibInstance != null) { + return SpineDartFFI(dylibInstance!, dylibInstance!.allocator); } else { throw Exception("Couldn't load libspine-flutter.js/.wasm"); } diff --git a/spine-flutter/lib/web_ffi/ffi/extensions.dart b/spine-flutter/lib/web_ffi/ffi/extensions.dart deleted file mode 100755 index 0234e5c94..000000000 --- a/spine-flutter/lib/web_ffi/ffi/extensions.dart +++ /dev/null @@ -1,253 +0,0 @@ -import 'dart:typed_data'; -import 'types.dart'; - -import '../modules/memory.dart'; -import '../modules/module.dart'; -import '../internal/marshaller.dart'; - -import '../web_ffi_meta.dart'; - -/// Extension on [Pointer] specialized for the type argument [NativeFunction]. -extension NativeFunctionPointer on Pointer> { - /// Convert to Dart function, automatically marshalling the arguments and return value. - /// - /// There are several rules that apply for the return type of `DF`, see - /// the list of [allowed return types](https://github.com/EPNW/web_ffi/blob/master/return_types.md). - /// If marshalling failes, a [MarshallingException] is thrown. - /// - /// If this is called on a pointer that does not point to a function, - /// a [ArgumentError](https://api.dart.dev/stable/dart-core/ArgumentError-class.html) is thrown. - DF asFunction() { - WasmSymbol symbol = symbolByAddress(boundMemory, address); - if (symbol is FunctionDescription) { - return marshall(symbol.function, boundMemory); - } else { - throw ArgumentError('No function at address $address was found (but a global symbol)!'); - } - } -} - -extension DynamicLibraryExtension on DynamicLibrary { - /// Helper that combines lookup and cast to a Dart function. - /// - /// This simply calles [DynamicLibrary.lookup] and [NativeFunctionPointer.asFunction] - /// internally, so see this two methods for additional insights. - F lookupFunction(String name) => - this.lookup>(name).asFunction(); -} - -/// Extension on [Allocator] to provide allocation with [NativeType]. -extension AllocatorAlloc on Allocator { - /// Allocates `sizeOf() * count` bytes of memory using [Allocator.allocate]. - /// - /// Since this calls [sizeOf] internally, an exception will be thrown if this - /// method is called with an @[unsized] type or before [Memory.init] was called. - Pointer call([int count = 1]) => allocate(sizeOf() * count); -} - -/// Extension on [Pointer] specialized for the type argument [Float]. -extension FloatPointer on Pointer { - /// The float at address. - double get value => this[0]; - void set value(double value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Float32List asTypedList(int length) => boundMemory.buffer.asFloat32List(address, length); - - /// The float at `address + size * index`. - double operator [](int index) => viewSingle(index).getFloat32(0, Memory.endianess); - void operator []=(int index, double value) => viewSingle(index).setFloat32(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [Double]. -extension DoublePointer on Pointer { - /// The double at address. - double get value => this[0]; - void set value(double value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Float64List asTypedList(int length) => boundMemory.buffer.asFloat64List(address, length); - - /// The double at `address + size * index`. - double operator [](int index) => viewSingle(index).getFloat64(0, Memory.endianess); - void operator []=(int index, double value) => viewSingle(index).setFloat64(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [Int8]. -extension Int8Pointer on Pointer { - /// The 8-bit integer at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Int8List asTypedList(int length) => boundMemory.buffer.asInt8List(address, length); - - /// The 8-bit integer at `address + size * index`. - int operator [](int index) => viewSingle(index).getInt8(0); - void operator []=(int index, int value) => viewSingle(index).setInt8(0, value); -} - -/// Extension on [Pointer] specialized for the type argument [Int16]. -extension Int16Pointer on Pointer { - /// The 16-bit integer at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Int16List asTypedList(int length) => boundMemory.buffer.asInt16List(address, length); - - /// The 16-bit integer at `address + size * index`. - int operator [](int index) => viewSingle(index).getInt16(0, Memory.endianess); - void operator []=(int index, int value) => viewSingle(index).setInt16(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [Int32]. -extension Int32Pointer on Pointer { - /// The 32-bit integer at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Int32List asTypedList(int length) => boundMemory.buffer.asInt32List(address, length); - - /// The 32-bit integer at `address + size * index`. - int operator [](int index) => viewSingle(index).getInt32(0, Memory.endianess); - void operator []=(int index, int value) => viewSingle(index).setInt32(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [Int64]. -extension Int64Pointer on Pointer { - /// The 64-bit integer at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Int64List asTypedList(int length) => boundMemory.buffer.asInt64List(address, length); - - /// The 64-bit integer at `address + size * index`. - int operator [](int index) => viewSingle(index).getInt64(0, Memory.endianess); - void operator []=(int index, int value) => viewSingle(index).setInt64(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [Uint8]. -extension Uint8Pointer on Pointer { - /// The 8-bit unsigned integer at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Uint8List asTypedList(int length) => boundMemory.buffer.asUint8List(address, length); - - /// The 8-bit unsigned integer at `address + size * index`. - int operator [](int index) => viewSingle(index).getUint8(0); - void operator []=(int index, int value) => viewSingle(index).setUint8(0, value); -} - -/// Extension on [Pointer] specialized for the type argument [Uint16]. -extension Uint16Pointer on Pointer { - /// The 16-bit unsigned integer at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Uint16List asTypedList(int length) => boundMemory.buffer.asUint16List(address, length); - - /// The 16-bit unsigned integer at `address + size * index`. - int operator [](int index) => viewSingle(index).getUint16(0, Memory.endianess); - void operator []=(int index, int value) => viewSingle(index).setUint16(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [Uint32]. -extension Uint32Pointer on Pointer { - /// The 32-bit unsigned integer at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Uint32List asTypedList(int length) => boundMemory.buffer.asUint32List(address, length); - - /// The 32-bit unsigned integer at `address + size * index`. - int operator [](int index) => viewSingle(index).getUint32(0, Memory.endianess); - void operator []=(int index, int value) => viewSingle(index).setUint32(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [Uint64]. -extension Uint64Pointer on Pointer { - /// The 64-bit unsigned integer at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Creates a typed list view backed by memory in the address space. - /// - /// The returned view will allow access to the memory range - /// from address to `address + size * length`. - Uint64List asTypedList(int length) => boundMemory.buffer.asUint64List(address, length); - - /// The 64-bit unsigned integer at `address + size * index`. - int operator [](int index) => viewSingle(index).getUint64(0, Memory.endianess); - void operator []=(int index, int value) => viewSingle(index).setUint64(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [IntPtr]. -extension IntPtrPointer on Pointer { - /// The 32-bit or 64-bit value at `address`. - int get value => this[0]; - void set value(int value) => this[0] = value; - - /// Returns `true` if the size of a pointer is 64-bit, `false` otherwise. - @extra - bool get is64Bit => size == 8; - - /// The 32-bit or 64-bit integer at `address + size * index`. - int operator [](int index) => - is64Bit ? viewSingle(index).getUint64(0, Memory.endianess) : viewSingle(index).getUint32(0, Memory.endianess); - void operator []=(int index, int value) => is64Bit - ? viewSingle(index).setUint64(0, value, Memory.endianess) - : viewSingle(index).setUint32(0, value, Memory.endianess); -} - -/// Extension on [Pointer] specialized for the type argument [Pointer]. -extension PointerPointer on Pointer> { - /// The pointer at `address`. - Pointer get value => this[0]; - void set value(Pointer value) => this[0] = value; - - /// Returns `true` if the size of a pointer is 64-bit, `false` otherwise. - @extra - bool get is64Bit => size == 8; - - /// The pointer at `address + size * index`. - Pointer operator [](int index) => new Pointer.fromAddress( - is64Bit ? viewSingle(index).getUint64(0, Memory.endianess) : viewSingle(index).getUint32(0, Memory.endianess), - boundMemory); - void operator []=(int index, Pointer value) => is64Bit - ? viewSingle(index).setUint64(0, value.address, Memory.endianess) - : viewSingle(index).setUint32(0, value.address, Memory.endianess); -} diff --git a/spine-flutter/lib/web_ffi/ffi/types.dart b/spine-flutter/lib/web_ffi/ffi/types.dart deleted file mode 100755 index 322a6d2b0..000000000 --- a/spine-flutter/lib/web_ffi/ffi/types.dart +++ /dev/null @@ -1,418 +0,0 @@ -import 'dart:typed_data'; -import 'package:meta/meta.dart'; - -import '../modules/module.dart'; -import '../modules/memory.dart'; -import '../modules/null_memory.dart'; - -import '../internal/type_utils.dart'; - -import '../web_ffi_meta.dart'; - -/// Represents a pointer into the native C memory corresponding to "NULL", -/// e.g. a pointer with address 0. -/// -/// You can compare any other pointer with this pointer using == to check -/// if it's also an nullpointer. -/// -/// Any other operation than comparing (e.g. calling [Pointer.cast]) -/// will result in exceptions. -final Pointer nullptr = new Pointer._null(); - -/// Number of bytes used by native type T. -/// -/// MUST NOT be called with types annoteted with @[unsized] or -/// before [Memory.init()] was called or else an exception will be thrown. -int sizeOf() { - int? size; - if (isPointerType()) { - size = sizeMap[IntPtr]; - } else { - size = sizeMap[T]; - } - if (size != null) { - return size; - } else { - throw new ArgumentError('The type $T is not known!'); - } -} - -bool _isUnsizedType() { - return isNativeFunctionType() || isVoidType(); -} - -/// [NativeType]'s subtypes represent a native type in C. -/// -/// [NativeType]'s subtypes (except [Pointer]) are not constructible -/// in the Dart code and serve purely as markers in type signatures. -@sealed -@notConstructible -class NativeType { - const NativeType(); -} - -/// Represents a native 64 bit double in C. -/// -/// Double is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Double extends NativeType { - const Double(); -} - -/// Represents a native 32 bit float in C. -/// -/// Float is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Float extends NativeType { - const Float(); -} - -/// Represents a native signed 8 bit integer in C. -/// -/// Int8 is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Int8 extends NativeType { - const Int8(); -} - -/// Represents a native signed 16 bit integer in C. -/// -/// Int16 is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Int16 extends NativeType { - const Int16(); -} - -/// Represents a native signed 32 bit integer in C. -/// -/// Int32 is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Int32 extends NativeType { - const Int32(); -} - -/// Represents a native signed 64 bit integer in C. -/// -/// Int64 is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Int64 extends NativeType { - const Int64(); -} - -/// Alias for Int64 (long long in C) -class LongLong extends Int64 { - const LongLong(); -} - -/// Represents a native unsigned 8 bit integer in C. -/// -/// Uint8 is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Uint8 extends NativeType { - const Uint8(); -} - -/// Alias for [Uint8] -/// Use Uint8 directly as typedef only works for function types -class UnsignedChar extends Uint8 { - const UnsignedChar(); -} - -/// Represents a native unsigned 16 bit integer in C. -/// -/// Uint16 is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Uint16 extends NativeType { - const Uint16(); -} - -/// Alias for [Uint16] -/// Use Uint16 directly as typedef only works for function types -class UnsignedShort extends Uint16 { - const UnsignedShort(); -} - -/// Represents a native unsigned 32 bit integer in C. -/// -/// Uint32 is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Uint32 extends NativeType { - const Uint32(); -} - -/// Represents a native unsigned 64 bit integer in C. -/// -/// Uint64 is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class Uint64 extends NativeType { - const Uint64(); -} - -/// Represents a native pointer-sized integer in C. -/// -/// IntPtr is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -class IntPtr extends NativeType {} - -/// Represents a native integer in C. -/// -/// The size is ABI-specific. For common platforms, this is usually 4 bytes -/// on 32-bit architectures and 8 bytes on 64-bit architectures. -@sealed -@notConstructible -class Int extends NativeType {} - -/// Represents a native size_t in C. -/// -/// The size is ABI-specific, typically same as pointer size. -@sealed -@notConstructible -class Size extends NativeType {} - -/// Represents a native bool in C. -/// -/// The size is typically 1 byte. -@sealed -@notConstructible -class Bool extends NativeType {} - -/// Represents a function type in C. -/// -/// NativeFunction is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -@unsized -class NativeFunction extends NativeType {} - -/// Opaque's subtypes represent opaque types in C. -/// -/// Classes that extend Opaque MUST NOT have a type argument! -/// -/// Opaque's subtypes are not constructible in the Dart code and serve -/// purely as markers in type signatures. -@noGeneric -@notConstructible -class Opaque extends NativeType {} - -/// Represents a void type in C. -/// -/// Void is not constructible in the Dart code and serves -/// purely as marker in type signatures. -@sealed -@notConstructible -@unsized -class Void extends NativeType {} - -/// Represents a char type in C -/// -/// Char is not constructible in the Dart code and serves -/// purely as a marker in type signatures -@sealed -@notConstructible -class Char extends Int8 { - const Char(); -} - -/// Represents a pointer into the native C memory. Cannot be extended. -@sealed -class Pointer extends NativeType { - //static Pointer> fromFunction(Function f, - // [Object? exceptionalReturn]) => - // throw new UnimplementedError(); - - /// Access to the raw pointer value. - final int address; - - /// The [Memory] object this pointer is bound to. - /// - /// The `Memory` object backs this pointer, if the value of - /// this pointer is accessed. - @extra - final Memory boundMemory; - - /// How much memory in bytes the type this pointer points to occupies, - /// or `null` for @[unsized] types. - @extra - final int? size; - - factory Pointer._null() { - return new Pointer._(0, new NullMemory(), null); - } - - /// Constructs a pointer from an address. - /// - /// The optional parameter `bindTo` can be ommited, if and only if - /// [Memory.global] is set, which is then used as `Memory` to bind to. - factory Pointer.fromAddress(int ptr, [Memory? bindTo]) { - bindTo = Memory.global; - Memory m; - if (bindTo != null) { - m = bindTo; - } else { - throw new StateError('No global memory set and no explcity memory to bind to given!'); - } - return new Pointer._(ptr, m, _isUnsizedType() ? null : sizeOf()); - } - - Pointer._(this.address, this.boundMemory, this.size); - - /// Casts this pointer to an other type. - Pointer cast() => - new Pointer._(address, boundMemory, _isUnsizedType() ? null : sizeOf()); - - /// Pointer arithmetic (takes element size into account). - /// - /// Throws an [UnsupportedError] if called on a pointer with an @[unsized] - /// type argument. - Pointer elementAt(int index) { - int? s = size; - if (s != null) { - return new Pointer._(address + index * s, boundMemory, s); - } else { - throw new UnsupportedError('elementAt is not supported for unsized types!'); - } - } - - /// The hash code for a Pointer only depends on its address. - @override - int get hashCode => address; - - /// Two pointers are equal if their address is the same, independently - /// of their type argument and of the memory they are bound to. - @override - bool operator ==(Object other) => (other is Pointer && other.address == address); - - /// Returns a view of a single element at [index] (takes element - /// size into account). - /// - /// Any modifications to the data will also alter the [Memory] object. - /// - /// Throws an [UnsupportedError] if called on a pointer with an @[unsized] - /// type argument. - @extra - ByteData viewSingle(int index) { - int? s = size; - if (s != null) { - return boundMemory.buffer.asByteData(address + index * s, s); - } else { - throw new UnsupportedError('viewSingle is not supported for unsized types!'); - } - } -} - -/// Represents a dynamically loaded C library. -class DynamicLibrary { - @extra - final Memory boundMemory; - - /// Creates a new instance based on the given module. - /// - /// While for each [DynamicLibrary] a new [Memory] object is - /// created, the [Memory] objects share the backing memory if - /// they are created based on the same module. - /// - /// The [registerMode] parameter can be used to control if the - /// newly created [Memory] object should be registered as - /// [Memory.global]. - @extra - factory DynamicLibrary.fromModule(Module module, - [MemoryRegisterMode registerMode = MemoryRegisterMode.onlyIfGlobalNotSet]) { - Memory memory = createMemory(module); - switch (registerMode) { - case MemoryRegisterMode.yes: - Memory.global = memory; - break; - case MemoryRegisterMode.no: - break; - case MemoryRegisterMode.onlyIfGlobalNotSet: - if (Memory.global == null) { - Memory.global = memory; - } - break; - } - return new DynamicLibrary._(memory); - } - - DynamicLibrary._(this.boundMemory); - - /// Looks up a symbol in the DynamicLibrary and returns its address in memory. - /// - /// Throws an [ArgumentError] if it fails to lookup the symbol. - /// - /// While this method checks if the underyling wasm symbol is a actually - /// a function when you lookup a [NativeFunction]``, it does not check if - /// the return type and parameters of `T` match the wasm function. - Pointer lookup(String name) { - WasmSymbol symbol = symbolByName(boundMemory, name); - if (isNativeFunctionType()) { - if (symbol is FunctionDescription) { - return new Pointer.fromAddress(symbol.tableIndex, boundMemory); - } else { - throw new ArgumentError('Tried to look up $name as a function, but it seems it is NOT a function!'); - } - } else { - return new Pointer.fromAddress(symbol.address, boundMemory); - } - } -} - -/// Manages memory on the native heap. -abstract class Allocator { - /// Allocates byteCount bytes of memory on the native heap. - /// - /// The parameter `alignment` is ignored. - Pointer allocate(int byteCount, {int? alignment}); - - /// Releases memory allocated on the native heap. - void free(Pointer pointer); -} - -/// Base class for all FFI struct types. -/// -/// This is a stub implementation for web_ffi compatibility. -/// Structs are not fully supported in web_ffi. -@unsized -class Struct extends NativeType {} - -/// Base class for all FFI union types. -/// -/// This is a stub implementation for web_ffi compatibility. -/// Unions are not fully supported in web_ffi. -@unsized -class Union extends NativeType {} - -/// Represents a fixed-size array of [T] in C. -/// -/// This is a stub implementation for web_ffi compatibility. -/// Arrays are not fully supported in web_ffi. -@unsized -class Array extends NativeType { - /// Constructor to allow [Array] declarations. - const Array(int dimension1, [int? dimension2, int? dimension3, int? dimension4, int? dimension5]); - - /// Constructor to allow [Array] declarations. - const Array.multi(List dimensions); -} diff --git a/spine-flutter/lib/web_ffi/ffi/utf8.dart b/spine-flutter/lib/web_ffi/ffi/utf8.dart deleted file mode 100644 index 25c11cab7..000000000 --- a/spine-flutter/lib/web_ffi/ffi/utf8.dart +++ /dev/null @@ -1,89 +0,0 @@ -// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file -// for details. All rights reserved. Use of this source code is governed by a -// BSD-style license that can be found in the LICENSE file. - -import 'dart:convert'; -import 'dart:typed_data'; -import 'types.dart'; -import 'extensions.dart'; -import '../modules/memory.dart'; - -/// The contents of a native zero-terminated array of UTF-8 code units. -/// -/// The Utf8 type itself has no functionality, it's only intended to be used -/// through a `Pointer` representing the entire array. This pointer is -/// the equivalent of a char pointer (`const char*`) in C code. -class Utf8 extends Opaque {} - -/// Extension method for converting a`Pointer` to a [String]. -extension Utf8Pointer on Pointer { - /// The number of UTF-8 code units in this zero-terminated UTF-8 string. - /// - /// The UTF-8 code units of the strings are the non-zero code units up to the - /// first zero code unit. - int get length { - _ensureNotNullptr('length'); - final codeUnits = cast(); - return _length(codeUnits); - } - - /// Converts this UTF-8 encoded string to a Dart string. - /// - /// Decodes the UTF-8 code units of this zero-terminated byte array as - /// Unicode code points and creates a Dart string containing those code - /// points. - /// - /// If [length] is provided, zero-termination is ignored and the result can - /// contain NUL characters. - /// - /// If [length] is not provided, the returned string is the string up til - /// but not including the first NUL character. - String toDartString({int? length}) { - _ensureNotNullptr('toDartString'); - final codeUnits = cast(); - if (length != null) { - RangeError.checkNotNegative(length, 'length'); - } else { - length = _length(codeUnits); - } - return utf8.decode(codeUnits.asTypedList(length)); - } - - static int _length(Pointer codeUnits) { - var length = 0; - while (codeUnits[length] != 0) { - length++; - } - return length; - } - - void _ensureNotNullptr(String operation) { - if (this == nullptr) { - throw UnsupportedError("Operation '$operation' not allowed on a 'nullptr'."); - } - } -} - -/// Extension method for converting a [String] to a `Pointer`. -extension StringUtf8Pointer on String { - /// Creates a zero-terminated [Utf8] code-unit array from this String. - /// - /// If this [String] contains NUL characters, converting it back to a string - /// using [Utf8Pointer.toDartString] will truncate the result if a length is - /// not passed. - /// - /// Unpaired surrogate code points in this [String] will be encoded as - /// replacement characters (U+FFFD, encoded as the bytes 0xEF 0xBF 0xBD) in - /// the UTF-8 encoded result. See [Utf8Encoder] for details on encoding. - /// - /// Returns an [allocator]-allocated pointer to the result. - Pointer toNativeUtf8({Allocator? allocator}) { - final alloc = allocator ?? Memory.global ?? (throw StateError('No allocator available')); - final units = utf8.encode(this); - final Pointer result = alloc(units.length + 1); - final Uint8List nativeString = result.asTypedList(units.length + 1); - nativeString.setAll(0, units); - nativeString[units.length] = 0; - return result.cast(); - } -} diff --git a/spine-flutter/lib/web_ffi/internal/invoker_generated.dart b/spine-flutter/lib/web_ffi/internal/invoker_generated.dart deleted file mode 100755 index dbb49bf1f..000000000 --- a/spine-flutter/lib/web_ffi/internal/invoker_generated.dart +++ /dev/null @@ -1,1089 +0,0 @@ -import '../ffi/types.dart'; -import '../modules/memory.dart'; -import 'marshaller.dart' show execute; - -/// https://stackoverflow.com/questions/26122009/is-there-a-maximum-number-of-parameters-for-functions-in-c-with-the-gcc-resp-m -/// the C Standard 5.2.4.1 says: -/// 4095 characters in a logical source line -/// 127 parameters in one function definition -/// 127 arguments in one function call - -class OpaqueInvokeHelper extends InvokeHelper> { - OpaqueInvokeHelper(Function? base, Memory? memory) : super(base, memory); - - @override - InvokeHelper> copyWith(Function base, Memory memory) { - return new OpaqueInvokeHelper(base, memory); - } - - @override - Pointer run( - [dynamic arg0, - dynamic arg1, - dynamic arg2, - dynamic arg3, - dynamic arg4, - dynamic arg5, - dynamic arg6, - dynamic arg7, - dynamic arg8, - dynamic arg9, - dynamic arg10, - dynamic arg11, - dynamic arg12, - dynamic arg13, - dynamic arg14, - dynamic arg15, - dynamic arg16, - dynamic arg17, - dynamic arg18, - dynamic arg19, - dynamic arg20, - dynamic arg21, - dynamic arg22, - dynamic arg23, - dynamic arg24, - dynamic arg25, - dynamic arg26, - dynamic arg27, - dynamic arg28, - dynamic arg29, - dynamic arg30, - dynamic arg31, - dynamic arg32, - dynamic arg33, - dynamic arg34, - dynamic arg35, - dynamic arg36, - dynamic arg37, - dynamic arg38, - dynamic arg39, - dynamic arg40, - dynamic arg41, - dynamic arg42, - dynamic arg43, - dynamic arg44, - dynamic arg45, - dynamic arg46, - dynamic arg47, - dynamic arg48, - dynamic arg49, - dynamic arg50, - dynamic arg51, - dynamic arg52, - dynamic arg53, - dynamic arg54, - dynamic arg55, - dynamic arg56, - dynamic arg57, - dynamic arg58, - dynamic arg59, - dynamic arg60, - dynamic arg61, - dynamic arg62, - dynamic arg63, - dynamic arg64, - dynamic arg65, - dynamic arg66, - dynamic arg67, - dynamic arg68, - dynamic arg69, - dynamic arg70, - dynamic arg71, - dynamic arg72, - dynamic arg73, - dynamic arg74, - dynamic arg75, - dynamic arg76, - dynamic arg77, - dynamic arg78, - dynamic arg79, - dynamic arg80, - dynamic arg81, - dynamic arg82, - dynamic arg83, - dynamic arg84, - dynamic arg85, - dynamic arg86, - dynamic arg87, - dynamic arg88, - dynamic arg89, - dynamic arg90, - dynamic arg91, - dynamic arg92, - dynamic arg93, - dynamic arg94, - dynamic arg95, - dynamic arg96, - dynamic arg97, - dynamic arg98, - dynamic arg99, - dynamic arg100, - dynamic arg101, - dynamic arg102, - dynamic arg103, - dynamic arg104, - dynamic arg105, - dynamic arg106, - dynamic arg107, - dynamic arg108, - dynamic arg109, - dynamic arg110, - dynamic arg111, - dynamic arg112, - dynamic arg113, - dynamic arg114, - dynamic arg115, - dynamic arg116, - dynamic arg117, - dynamic arg118, - dynamic arg119, - dynamic arg120, - dynamic arg121, - dynamic arg122, - dynamic arg123, - dynamic arg124, - dynamic arg125, - dynamic arg126]) => - new InvokeHelper>(_base, _memory) - .run( - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - arg6, - arg7, - arg8, - arg9, - arg10, - arg11, - arg12, - arg13, - arg14, - arg15, - arg16, - arg17, - arg18, - arg19, - arg20, - arg21, - arg22, - arg23, - arg24, - arg25, - arg26, - arg27, - arg28, - arg29, - arg30, - arg31, - arg32, - arg33, - arg34, - arg35, - arg36, - arg37, - arg38, - arg39, - arg40, - arg41, - arg42, - arg43, - arg44, - arg45, - arg46, - arg47, - arg48, - arg49, - arg50, - arg51, - arg52, - arg53, - arg54, - arg55, - arg56, - arg57, - arg58, - arg59, - arg60, - arg61, - arg62, - arg63, - arg64, - arg65, - arg66, - arg67, - arg68, - arg69, - arg70, - arg71, - arg72, - arg73, - arg74, - arg75, - arg76, - arg77, - arg78, - arg79, - arg80, - arg81, - arg82, - arg83, - arg84, - arg85, - arg86, - arg87, - arg88, - arg89, - arg90, - arg91, - arg92, - arg93, - arg94, - arg95, - arg96, - arg97, - arg98, - arg99, - arg100, - arg101, - arg102, - arg103, - arg104, - arg105, - arg106, - arg107, - arg108, - arg109, - arg110, - arg111, - arg112, - arg113, - arg114, - arg115, - arg116, - arg117, - arg118, - arg119, - arg120, - arg121, - arg122, - arg123, - arg124, - arg125, - arg126) - .cast(); -} - -class OpaqueInvokeHelperSquare extends InvokeHelper>> { - OpaqueInvokeHelperSquare(Function? base, Memory? memory) : super(base, memory); - - @override - InvokeHelper>> copyWith(Function base, Memory memory) { - return new OpaqueInvokeHelperSquare(base, memory); - } - - @override - Pointer> run( - [dynamic arg0, - dynamic arg1, - dynamic arg2, - dynamic arg3, - dynamic arg4, - dynamic arg5, - dynamic arg6, - dynamic arg7, - dynamic arg8, - dynamic arg9, - dynamic arg10, - dynamic arg11, - dynamic arg12, - dynamic arg13, - dynamic arg14, - dynamic arg15, - dynamic arg16, - dynamic arg17, - dynamic arg18, - dynamic arg19, - dynamic arg20, - dynamic arg21, - dynamic arg22, - dynamic arg23, - dynamic arg24, - dynamic arg25, - dynamic arg26, - dynamic arg27, - dynamic arg28, - dynamic arg29, - dynamic arg30, - dynamic arg31, - dynamic arg32, - dynamic arg33, - dynamic arg34, - dynamic arg35, - dynamic arg36, - dynamic arg37, - dynamic arg38, - dynamic arg39, - dynamic arg40, - dynamic arg41, - dynamic arg42, - dynamic arg43, - dynamic arg44, - dynamic arg45, - dynamic arg46, - dynamic arg47, - dynamic arg48, - dynamic arg49, - dynamic arg50, - dynamic arg51, - dynamic arg52, - dynamic arg53, - dynamic arg54, - dynamic arg55, - dynamic arg56, - dynamic arg57, - dynamic arg58, - dynamic arg59, - dynamic arg60, - dynamic arg61, - dynamic arg62, - dynamic arg63, - dynamic arg64, - dynamic arg65, - dynamic arg66, - dynamic arg67, - dynamic arg68, - dynamic arg69, - dynamic arg70, - dynamic arg71, - dynamic arg72, - dynamic arg73, - dynamic arg74, - dynamic arg75, - dynamic arg76, - dynamic arg77, - dynamic arg78, - dynamic arg79, - dynamic arg80, - dynamic arg81, - dynamic arg82, - dynamic arg83, - dynamic arg84, - dynamic arg85, - dynamic arg86, - dynamic arg87, - dynamic arg88, - dynamic arg89, - dynamic arg90, - dynamic arg91, - dynamic arg92, - dynamic arg93, - dynamic arg94, - dynamic arg95, - dynamic arg96, - dynamic arg97, - dynamic arg98, - dynamic arg99, - dynamic arg100, - dynamic arg101, - dynamic arg102, - dynamic arg103, - dynamic arg104, - dynamic arg105, - dynamic arg106, - dynamic arg107, - dynamic arg108, - dynamic arg109, - dynamic arg110, - dynamic arg111, - dynamic arg112, - dynamic arg113, - dynamic arg114, - dynamic arg115, - dynamic arg116, - dynamic arg117, - dynamic arg118, - dynamic arg119, - dynamic arg120, - dynamic arg121, - dynamic arg122, - dynamic arg123, - dynamic arg124, - dynamic arg125, - dynamic arg126]) => - new InvokeHelper>>(_base, _memory) - .run( - arg0, - arg1, - arg2, - arg3, - arg4, - arg5, - arg6, - arg7, - arg8, - arg9, - arg10, - arg11, - arg12, - arg13, - arg14, - arg15, - arg16, - arg17, - arg18, - arg19, - arg20, - arg21, - arg22, - arg23, - arg24, - arg25, - arg26, - arg27, - arg28, - arg29, - arg30, - arg31, - arg32, - arg33, - arg34, - arg35, - arg36, - arg37, - arg38, - arg39, - arg40, - arg41, - arg42, - arg43, - arg44, - arg45, - arg46, - arg47, - arg48, - arg49, - arg50, - arg51, - arg52, - arg53, - arg54, - arg55, - arg56, - arg57, - arg58, - arg59, - arg60, - arg61, - arg62, - arg63, - arg64, - arg65, - arg66, - arg67, - arg68, - arg69, - arg70, - arg71, - arg72, - arg73, - arg74, - arg75, - arg76, - arg77, - arg78, - arg79, - arg80, - arg81, - arg82, - arg83, - arg84, - arg85, - arg86, - arg87, - arg88, - arg89, - arg90, - arg91, - arg92, - arg93, - arg94, - arg95, - arg96, - arg97, - arg98, - arg99, - arg100, - arg101, - arg102, - arg103, - arg104, - arg105, - arg106, - arg107, - arg108, - arg109, - arg110, - arg111, - arg112, - arg113, - arg114, - arg115, - arg116, - arg117, - arg118, - arg119, - arg120, - arg121, - arg122, - arg123, - arg124, - arg125, - arg126) - .cast>(); -} - -class InvokeHelper { - final Memory? _memory; - final Function? _base; - - const InvokeHelper(this._base, this._memory); - - InvokeHelper copyWith(Function base, Memory memory) { - return new InvokeHelper(base, memory); - } - - T run( - [dynamic arg0, - dynamic arg1, - dynamic arg2, - dynamic arg3, - dynamic arg4, - dynamic arg5, - dynamic arg6, - dynamic arg7, - dynamic arg8, - dynamic arg9, - dynamic arg10, - dynamic arg11, - dynamic arg12, - dynamic arg13, - dynamic arg14, - dynamic arg15, - dynamic arg16, - dynamic arg17, - dynamic arg18, - dynamic arg19, - dynamic arg20, - dynamic arg21, - dynamic arg22, - dynamic arg23, - dynamic arg24, - dynamic arg25, - dynamic arg26, - dynamic arg27, - dynamic arg28, - dynamic arg29, - dynamic arg30, - dynamic arg31, - dynamic arg32, - dynamic arg33, - dynamic arg34, - dynamic arg35, - dynamic arg36, - dynamic arg37, - dynamic arg38, - dynamic arg39, - dynamic arg40, - dynamic arg41, - dynamic arg42, - dynamic arg43, - dynamic arg44, - dynamic arg45, - dynamic arg46, - dynamic arg47, - dynamic arg48, - dynamic arg49, - dynamic arg50, - dynamic arg51, - dynamic arg52, - dynamic arg53, - dynamic arg54, - dynamic arg55, - dynamic arg56, - dynamic arg57, - dynamic arg58, - dynamic arg59, - dynamic arg60, - dynamic arg61, - dynamic arg62, - dynamic arg63, - dynamic arg64, - dynamic arg65, - dynamic arg66, - dynamic arg67, - dynamic arg68, - dynamic arg69, - dynamic arg70, - dynamic arg71, - dynamic arg72, - dynamic arg73, - dynamic arg74, - dynamic arg75, - dynamic arg76, - dynamic arg77, - dynamic arg78, - dynamic arg79, - dynamic arg80, - dynamic arg81, - dynamic arg82, - dynamic arg83, - dynamic arg84, - dynamic arg85, - dynamic arg86, - dynamic arg87, - dynamic arg88, - dynamic arg89, - dynamic arg90, - dynamic arg91, - dynamic arg92, - dynamic arg93, - dynamic arg94, - dynamic arg95, - dynamic arg96, - dynamic arg97, - dynamic arg98, - dynamic arg99, - dynamic arg100, - dynamic arg101, - dynamic arg102, - dynamic arg103, - dynamic arg104, - dynamic arg105, - dynamic arg106, - dynamic arg107, - dynamic arg108, - dynamic arg109, - dynamic arg110, - dynamic arg111, - dynamic arg112, - dynamic arg113, - dynamic arg114, - dynamic arg115, - dynamic arg116, - dynamic arg117, - dynamic arg118, - dynamic arg119, - dynamic arg120, - dynamic arg121, - dynamic arg122, - dynamic arg123, - dynamic arg124, - dynamic arg125, - dynamic arg126]) { - if (_base == null || _memory == null) { - throw StateError('Call copyWith first!'); - } - Function base = _base!; - Memory memory = _memory!; - List args = []; - if (arg0 != null) { - args.add(arg0); - if (arg1 != null) { - args.add(arg1); - if (arg2 != null) { - args.add(arg2); - if (arg3 != null) { - args.add(arg3); - if (arg4 != null) { - args.add(arg4); - if (arg5 != null) { - args.add(arg5); - if (arg6 != null) { - args.add(arg6); - if (arg7 != null) { - args.add(arg7); - if (arg8 != null) { - args.add(arg8); - if (arg9 != null) { - args.add(arg9); - if (arg10 != null) { - args.add(arg10); - if (arg11 != null) { - args.add(arg11); - if (arg12 != null) { - args.add(arg12); - if (arg13 != null) { - args.add(arg13); - if (arg14 != null) { - args.add(arg14); - if (arg15 != null) { - args.add(arg15); - if (arg16 != null) { - args.add(arg16); - if (arg17 != null) { - args.add(arg17); - if (arg18 != null) { - args.add(arg18); - if (arg19 != null) { - args.add(arg19); - if (arg20 != null) { - args.add(arg20); - if (arg21 != null) { - args.add(arg21); - if (arg22 != null) { - args.add(arg22); - if (arg23 != null) { - args.add(arg23); - if (arg24 != null) { - args.add(arg24); - if (arg25 != null) { - args.add(arg25); - if (arg26 != null) { - args.add(arg26); - if (arg27 != null) { - args.add(arg27); - if (arg28 != null) { - args.add(arg28); - if (arg29 != null) { - args.add(arg29); - if (arg30 != null) { - args.add(arg30); - if (arg31 != null) { - args.add(arg31); - if (arg32 != null) { - args.add(arg32); - if (arg33 != null) { - args.add(arg33); - if (arg34 != null) { - args.add(arg34); - if (arg35 != null) { - args.add(arg35); - if (arg36 != null) { - args.add(arg36); - if (arg37 != null) { - args.add(arg37); - if (arg38 != null) { - args.add(arg38); - if (arg39 != null) { - args.add(arg39); - if (arg40 != null) { - args.add(arg40); - if (arg41 != null) { - args.add(arg41); - if (arg42 != null) { - args.add(arg42); - if (arg43 != null) { - args.add(arg43); - if (arg44 != null) { - args.add(arg44); - if (arg45 != null) { - args.add(arg45); - if (arg46 != null) { - args.add(arg46); - if (arg47 != null) { - args.add(arg47); - if (arg48 != null) { - args.add(arg48); - if (arg49 != - null) { - args.add(arg49); - if (arg50 != - null) { - args.add( - arg50); - if (arg51 != - null) { - args.add( - arg51); - if (arg52 != - null) { - args.add( - arg52); - if (arg53 != - null) { - args.add( - arg53); - if (arg54 != - null) { - args.add( - arg54); - if (arg55 != - null) { - args.add(arg55); - if (arg56 != - null) { - args.add(arg56); - if (arg57 != null) { - args.add(arg57); - if (arg58 != null) { - args.add(arg58); - if (arg59 != null) { - args.add(arg59); - if (arg60 != null) { - args.add(arg60); - if (arg61 != null) { - args.add(arg61); - if (arg62 != null) { - args.add(arg62); - if (arg63 != null) { - args.add(arg63); - if (arg64 != null) { - args.add(arg64); - if (arg65 != null) { - args.add(arg65); - if (arg66 != null) { - args.add(arg66); - if (arg67 != null) { - args.add(arg67); - if (arg68 != null) { - args.add(arg68); - if (arg69 != null) { - args.add(arg69); - if (arg70 != null) { - args.add(arg70); - if (arg71 != null) { - args.add(arg71); - if (arg72 != null) { - args.add(arg72); - if (arg73 != null) { - args.add(arg73); - if (arg74 != null) { - args.add(arg74); - if (arg75 != null) { - args.add(arg75); - if (arg76 != null) { - args.add(arg76); - if (arg77 != null) { - args.add(arg77); - if (arg78 != null) { - args.add(arg78); - if (arg79 != null) { - args.add(arg79); - if (arg80 != null) { - args.add(arg80); - if (arg81 != null) { - args.add(arg81); - if (arg82 != null) { - args.add(arg82); - if (arg83 != null) { - args.add(arg83); - if (arg84 != null) { - args.add(arg84); - if (arg85 != null) { - args.add(arg85); - if (arg86 != null) { - args.add(arg86); - if (arg87 != null) { - args.add(arg87); - if (arg88 != null) { - args.add(arg88); - if (arg89 != null) { - args.add(arg89); - if (arg90 != null) { - args.add(arg90); - if (arg91 != null) { - args.add(arg91); - if (arg92 != null) { - args.add(arg92); - if (arg93 != null) { - args.add(arg93); - if (arg94 != null) { - args.add(arg94); - if (arg95 != null) { - args.add(arg95); - if (arg96 != null) { - args.add(arg96); - if (arg97 != null) { - args.add(arg97); - if (arg98 != null) { - args.add(arg98); - if (arg99 != null) { - args.add(arg99); - if (arg100 != null) { - args.add(arg100); - if (arg101 != null) { - args.add(arg101); - if (arg102 != null) { - args.add(arg102); - if (arg103 != null) { - args.add(arg103); - if (arg104 != null) { - args.add(arg104); - if (arg105 != null) { - args.add(arg105); - if (arg106 != null) { - args.add(arg106); - if (arg107 != null) { - args.add(arg107); - if (arg108 != null) { - args.add(arg108); - if (arg109 != null) { - args.add(arg109); - if (arg110 != null) { - args.add(arg110); - if (arg111 != null) { - args.add(arg111); - if (arg112 != null) { - args.add(arg112); - if (arg113 != null) { - args.add(arg113); - if (arg114 != null) { - args.add(arg114); - if (arg115 != null) { - args.add(arg115); - if (arg116 != null) { - args.add(arg116); - if (arg117 != null) { - args.add(arg117); - if (arg118 != null) { - args.add(arg118); - if (arg119 != null) { - args.add(arg119); - if (arg120 != null) { - args.add(arg120); - if (arg121 != null) { - args.add(arg121); - if (arg122 != null) { - args.add(arg122); - if (arg123 != null) { - args.add(arg123); - if (arg124 != null) { - args.add(arg124); - if (arg125 != null) { - args.add(arg125); - if (arg126 != null) { - args.add(arg126); - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - } - return execute(base, args, memory); - } -} diff --git a/spine-flutter/lib/web_ffi/internal/marshaller.dart b/spine-flutter/lib/web_ffi/internal/marshaller.dart deleted file mode 100755 index 726b78643..000000000 --- a/spine-flutter/lib/web_ffi/internal/marshaller.dart +++ /dev/null @@ -1,278 +0,0 @@ -import 'package:meta/meta.dart'; - -import '../ffi/types.dart'; -import '../modules/exceptions.dart'; -import '../modules/memory.dart'; -import 'invoker_generated.dart'; -import 'type_utils.dart'; - -// Called from the invokers -T execute(Function base, List args, Memory memory) { - if (T == DartVoidType) { - Function.apply(base, args.map(_toJsType).toList()); - return null as T; - } else { - Object result = Function.apply(base, args.map(_toJsType).toList()); - return _toDartType(result, memory); - } -} - -DF marshall(Function base, Memory memory) { - return _inferFromSignature(DF.toString()).copyWith(base, memory).run as DF; -} - -Object _toJsType(Object dartObject) { - if (dartObject is int || dartObject is double || dartObject is bool) { - return dartObject; - } else if (dartObject is Pointer) { - return dartObject.address; - } else { - throw new MarshallingException('Could not convert dart type ${dartObject.runtimeType} to a JavaScript type!'); - } -} - -InvokeHelper _inferFromSignature(String signature) { - String returnType = signature.split('=>').last.trim(); - if (returnType.startsWith(pointerPointerPointerPrefix)) { - throw new MarshallingException('Nesting pointers is only supported to a deepth of 2!' + - '\nThis means that you can write Pointer> but not Pointer>>, ...'); - } - InvokeHelper? h = _knownTypes[returnType]; - if (h != null) { - return h; - } else { - if (returnType.startsWith(pointerNativeFunctionPrefix)) { - throw new MarshallingException( - 'Using pointers to native functions as return type is only allowed if the type of the native function is dynamic!' + - '\nThis means that only Pointer> is allowed!'); - } else { - throw new MarshallingException( - 'Unknown type $returnType (infered from $signature), all marshallable types: ${listKnownTypes()}'); - } - } -} - -@visibleForTesting -List listKnownTypes() => new List.of(_knownTypes.keys, growable: false); - -final Map _knownTypes = { - typeString(): new InvokeHelper(null, null), - typeString(): new InvokeHelper(null, null), - typeString(): new InvokeHelper(null, null), - typeString(): new InvokeHelper(null, null) -}; - -void registerNativeMarshallerType() { - _knownTypes[typeString>()] = new InvokeHelper>(null, null); - _knownTypes[typeString>>()] = new InvokeHelper>>(null, null); -} - -void registerNativeMarshallerOpaque() { - _knownTypes[typeString>()] = new OpaqueInvokeHelper(null, null); - _knownTypes[typeString>>()] = new OpaqueInvokeHelperSquare(null, null); -} - -T _toDartType(Object o, Memory bind) { - if (T == int) { - if (o is int) { - return o as T; - } else { - throw new MarshallingException.typeMissmatch(T, o); - } - } else if (T == double) { - if (o is double) { - return o as T; - } else { - throw new MarshallingException.typeMissmatch(T, o); - } - } else if (T == bool) { - if (o is bool) { - return o as T; - } else if (o is int) { - // Handle C convention where bool is represented as int (0 = false, non-zero = true) - return (o != 0) as T; - } else { - throw new MarshallingException.typeMissmatch(T, o); - } - } else { - if (T == Pointer_Void) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_IntPtr) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Int8) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Int16) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Int32) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Int64) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Double) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Uint8) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Uint16) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Uint32) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Uint64) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Float) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Char) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Opaque) { - if (o is int) { - return new Pointer.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_NativeFunction_dynamic) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else { - if (T == Pointer_Pointer_Void) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_IntPtr) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Int8) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Int16) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Int32) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Int64) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Double) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Uint8) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Uint16) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Uint32) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Uint64) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Char) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Float) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else if (T == Pointer_Pointer_Opaque) { - if (o is int) { - return new Pointer>.fromAddress(o, bind) as T; - } else { - throw new MarshallingException.noAddress(o); - } - } else { - throw new MarshallingException('Can not back-marshall to type $T (object type is ${o.runtimeType}'); - } - } - } -} diff --git a/spine-flutter/lib/web_ffi/internal/type_utils.dart b/spine-flutter/lib/web_ffi/internal/type_utils.dart deleted file mode 100755 index a3966238c..000000000 --- a/spine-flutter/lib/web_ffi/internal/type_utils.dart +++ /dev/null @@ -1,55 +0,0 @@ -import '../ffi/types.dart'; - -/// Hacky workadround, see https://github.com/dart-lang/language/issues/123 -Type _extractType() => T; -String typeString() => _extractType().toString(); - -// Variable names begin with a capital letter on purpose (opposing dart conventions) to hilight that -// they are treated like types (which are written with a captial letter in dart). -final Type Pointer_IntPtr = _extractType>(); -final Type Pointer_Void = _extractType>(); -final Type Pointer_Int8 = _extractType>(); -final Type Pointer_Int16 = _extractType>(); -final Type Pointer_Int32 = _extractType>(); -final Type Pointer_Int64 = _extractType>(); -final Type Pointer_Double = _extractType>(); -final Type Pointer_Uint8 = _extractType>(); -final Type Pointer_Uint16 = _extractType>(); -final Type Pointer_Uint32 = _extractType>(); -final Type Pointer_Uint64 = _extractType>(); -final Type Pointer_Char = _extractType>(); -final Type Pointer_Float = _extractType>(); -final Type Pointer_Opaque = _extractType>(); -final Type Pointer_Pointer_IntPtr = _extractType>>(); -final Type Pointer_Pointer_Void = _extractType>>(); -final Type Pointer_Pointer_Int8 = _extractType>>(); -final Type Pointer_Pointer_Int16 = _extractType>>(); -final Type Pointer_Pointer_Int32 = _extractType>>(); -final Type Pointer_Pointer_Int64 = _extractType>>(); -final Type Pointer_Pointer_Double = _extractType>>(); -final Type Pointer_Pointer_Uint8 = _extractType>>(); -final Type Pointer_Pointer_Uint16 = _extractType>>(); -final Type Pointer_Pointer_Uint32 = _extractType>>(); -final Type Pointer_Pointer_Uint64 = _extractType>>(); -final Type Pointer_Pointer_Char = _extractType>>(); -final Type Pointer_Pointer_Float = _extractType>>(); -final Type Pointer_Pointer_Opaque = _extractType>>(); -final Type Pointer_NativeFunction_dynamic = _extractType>>(); -final Type DartVoidType = _extractType(); -final Type FfiVoidType = _extractType(); - -final String _dynamicTypeString = typeString(); - -final String pointerPointerPointerPrefix = - typeString>>>().split(_dynamicTypeString).first; - -final String pointerNativeFunctionPrefix = - typeString>>().split(_dynamicTypeString).first; - -final String _nativeFunctionPrefix = typeString>().split(_dynamicTypeString).first; -bool isNativeFunctionType() => typeString().startsWith(_nativeFunctionPrefix); - -final String _pointerPrefix = typeString>().split(_dynamicTypeString).first; -bool isPointerType() => typeString().startsWith(_pointerPrefix); - -bool isVoidType() => _extractType() == FfiVoidType; diff --git a/spine-flutter/lib/web_ffi/meta/meta.dart b/spine-flutter/lib/web_ffi/meta/meta.dart deleted file mode 100755 index d2329466e..000000000 --- a/spine-flutter/lib/web_ffi/meta/meta.dart +++ /dev/null @@ -1,35 +0,0 @@ -class _Extra { - const _Extra(); -} - -/// A class, field or method annotated with extra is present in `web_ffi`, -/// but not in `dart:ffi`. -const _Extra extra = const _Extra(); - -class _NoGeneric { - const _NoGeneric(); -} - -/// If a class which is annotead with [noGeneric] is extended or implemented, -/// the derived class MUST NOT impose a type argument! -const _NoGeneric noGeneric = const _NoGeneric(); - -class _NotConstructible { - const _NotConstructible(); -} - -/// A [NativeType] annotated with unsized should not be instantiated. -/// -/// However, they are not marked as `abstract` to meet the dart:ffi API. -const _NotConstructible notConstructible = const _NotConstructible(); - -class _Unsized { - const _Unsized(); -} - -/// A [NativeType] annotated with unsized does not have a predefined size. -/// -/// Unsized [NativeType]s do not support [sizeOf] because their size is unknown, -/// so calling [sizeOf] with an @[unsized] [NativeType] will throw an exception. -/// Consequently, [Pointer.elementAt] is not available and will also throw an exception. -const _Unsized unsized = const _Unsized(); diff --git a/spine-flutter/lib/web_ffi/modules/emscripten/emscripten_module.dart b/spine-flutter/lib/web_ffi/modules/emscripten/emscripten_module.dart deleted file mode 100755 index 718651c43..000000000 --- a/spine-flutter/lib/web_ffi/modules/emscripten/emscripten_module.dart +++ /dev/null @@ -1,186 +0,0 @@ -@JS() -library emscripten_module; - -import 'dart:typed_data'; -import 'package:js/js.dart'; -import 'package:js/js_util.dart'; -import '../module.dart'; -import '../../web_ffi_meta.dart'; - -@JS('globalThis') -external Object get _globalThis; - -@JS('Object.entries') -external List? _entries(Object? o); - -@JS() -@anonymous -class _EmscriptenModuleJs { - external Uint8List? get wasmBinary; - external Uint8List? get HEAPU8; - external Object? get asm; - external Object? get wasmExports; - - // Must have an unnamed factory constructor with named arguments. - external factory _EmscriptenModuleJs({Uint8List wasmBinary}); -} - -const String _github = r'https://github.com/EPNW/web_ffi'; -String _adu(WasmSymbol? original, WasmSymbol? tried) => - 'CRITICAL EXCEPTION! Address double use! This should never happen, please report this issue on github immediately at $_github' + - '\r\nOriginal: $original' + - '\r\nTried: $tried'; - -typedef int _Malloc(int size); -typedef void _Free(int address); - -FunctionDescription _fromWasmFunction(String name, Function func) { - String? s = getProperty(func, 'name'); - if (s != null) { - int? index = int.tryParse(s); - if (index != null) { - int? length = getProperty(func, 'length'); - if (length != null) { - return new FunctionDescription(tableIndex: index, name: name, function: func, argumentCount: length); - } else { - throw new ArgumentError('$name does not seem to be a function symbol!'); - } - } else { - throw new ArgumentError('$name does not seem to be a function symbol!'); - } - } else { - throw new ArgumentError('$name does not seem to be a function symbol!'); - } -} - -/// Documentation is in `emscripten_module_stub.dart`! -@extra -class EmscriptenModule extends Module { - static Function _moduleFunction(String moduleName) { - Function? moduleFunction = getProperty(_globalThis, moduleName); - if (moduleFunction != null) { - return moduleFunction; - } else { - throw StateError('Could not find a emscripten module named $moduleName'); - } - } - - /// Documentation is in `emscripten_module_stub.dart`! - static Future process(String moduleName) async { - Function moduleFunction = _moduleFunction(moduleName); - _EmscriptenModuleJs module = new _EmscriptenModuleJs(); - Object? o = moduleFunction(module); - if (o != null) { - await promiseToFuture(o); - return new EmscriptenModule._fromJs(module); - } else { - throw new StateError('Could not instantiate an emscripten module!'); - } - } - - /// Documentation is in `emscripten_module_stub.dart`! - static Future compile(Uint8List wasmBinary, String moduleName) async { - Function moduleFunction = _moduleFunction(moduleName); - _EmscriptenModuleJs module = new _EmscriptenModuleJs(wasmBinary: wasmBinary); - Object? o = moduleFunction(module); - if (o != null) { - await promiseToFuture(o); - return new EmscriptenModule._fromJs(module); - } else { - throw new StateError('Could not instantiate an emscripten module!'); - } - } - - final _EmscriptenModuleJs _emscriptenModuleJs; - final List _exports; - final _Malloc _malloc; - final _Free _free; - - @override - List get exports => _exports; - - EmscriptenModule._(this._emscriptenModuleJs, this._exports, this._malloc, this._free); - - factory EmscriptenModule._fromJs(_EmscriptenModuleJs module) { - Object? asm; - if (module.wasmExports != null) { - asm = module.wasmExports; - } else if (module.asm != null) { - asm = module.asm; - } else { - throw Exception('Neither wasmExports nor asm is available in the module'); - } - if (asm != null) { - Map knownAddresses = {}; - _Malloc? malloc; - _Free? free; - List exports = []; - List? entries = _entries(asm); - if (entries != null) { - for (dynamic entry in entries) { - if (entry is List) { - Object value = entry.last; - if (value is int) { - Global g = new Global(address: value, name: entry.first as String); - if (knownAddresses.containsKey(value) && knownAddresses[value] is! Global) { - throw new StateError(_adu(knownAddresses[value], g)); - } - knownAddresses[value] = g; - exports.add(g); - } else if (value is Function) { - FunctionDescription description = _fromWasmFunction(entry.first as String, value); - // It might happen that there are two different c functions that do nothing else than calling the same underlying c function - // In this case, a compiler might substitute both functions with the underlying c function - // So we got two functions with different names at the same table index - // So it is actually ok if there are two things at the same address, as long as they are both functions - if (knownAddresses.containsKey(description.tableIndex) && - knownAddresses[description.tableIndex] is! FunctionDescription) { - throw new StateError(_adu(knownAddresses[description.tableIndex], description)); - } - knownAddresses[description.tableIndex] = description; - exports.add(description); - if (description.name == 'malloc') { - malloc = description.function as _Malloc; - } else if (description.name == 'free') { - free = description.function as _Free; - } - } - } else { - throw new StateError('Unexpected entry in entries(Module[\'asm\'])!'); - } - } - if (malloc != null) { - if (free != null) { - return new EmscriptenModule._(module, exports, malloc, free); - } else { - throw new StateError('Module does not export the free function!'); - } - } else { - throw new StateError('Module does not export the malloc function!'); - } - } else { - throw new StateError('JavaScript error: Could not access entries of Module[\'asm\']!'); - } - } else { - throw new StateError( - 'Could not access Module[\'asm\'], are your sure your module was compiled using emscripten?'); - } - } - - @override - void free(int pointer) => _free(pointer); - - @override - ByteBuffer get heap => _getHeap(); - ByteBuffer _getHeap() { - Uint8List? h = _emscriptenModuleJs.HEAPU8; - if (h != null) { - return h.buffer; - } else { - throw StateError('Unexpected memory error!'); - } - } - - @override - int malloc(int size) => _malloc(size); -} diff --git a/spine-flutter/lib/web_ffi/modules/emscripten/emscripten_module_stub.dart b/spine-flutter/lib/web_ffi/modules/emscripten/emscripten_module_stub.dart deleted file mode 100755 index 583db0b5e..000000000 --- a/spine-flutter/lib/web_ffi/modules/emscripten/emscripten_module_stub.dart +++ /dev/null @@ -1,68 +0,0 @@ -import 'dart:typed_data'; -import '../module.dart'; - -import '../../web_ffi_meta.dart'; - -/// Provides access to WebAssembly compiled with [emscripten](https://emscripten.org). -/// -/// WebAssembly compiled with emscripten comes with an `.wasm` -/// and an additional `.js` glue JavaScript file. The later is -/// required to be loaded on the page before calling any of this classes -/// functions. -/// -/// The WebAssembly must have been compiled with the `-s MODULARIZE=1` -/// and `-s EXPORT_NAME=` flags. Futhermore the `` -/// must contain all exported WebAssembly functions that should be usable from -/// dart, so using `-s MAIN_MODULE=1` might be advisable. -/// -/// For a detailed walkthrough on how to create and inject these files, -/// see the [example](https://github.com/EPNW/web_ffi/blob/master/example/README.md). -/// -/// On platforms where [dart:js](https://api.dart.dev/stable/dart-js/dart-js-library.html) -/// is not available, all methods throw [UnsupportedError]s. -@extra -class EmscriptenModule extends Module { - /// Connects to the JavaScript glue of the emscripten module. - /// - /// This happens in the following way: - /// First, a JavaScript property named `moduleName` of the global object - /// is accessed, which should contain a function. Then this function is - /// called and expected to return a JavaScript emscripten module. - /// - /// The JavaScript emscripten module is responsible for retriving the - /// WebAssembly and compile it accordingly. - /// - /// On platforms where [dart:js](https://api.dart.dev/stable/dart-js/dart-js-library.html) - /// is not available, an [UnsupportedError] is thrown. - static Future process(String moduleName) => - throw new UnsupportedError('Emscripten operations are only allowed on the web (where dart:js is present)!'); - - /// Connects to the JavaScript glue of the emscripten module. - /// - /// Works like [process], except that the bytes of the WebAssembly - /// are passed to the JavaScript emscripten module, so it is - /// your responsibility to fetch it. - /// - /// On platforms where [dart:js](https://api.dart.dev/stable/dart-js/dart-js-library.html) - /// is not available, an [UnsupportedError] is thrown. - static Future compile(Uint8List wasmBinary, String moduleName) => - throw new UnsupportedError('Emscripten operations are only allowed on the web (where dart:js is present)!'); - - EmscriptenModule._(); - - @override - List get exports => - throw new UnsupportedError('Emscripten operations are only allowed on the web (where dart:js is present)!'); - - @override - void free(int pointer) => - throw new UnsupportedError('Emscripten operations are only allowed on the web (where dart:js is present)!'); - - @override - ByteBuffer get heap => - throw new UnsupportedError('Emscripten operations are only allowed on the web (where dart:js is present)!'); - - @override - int malloc(int size) => - throw new UnsupportedError('Emscripten operations are only allowed on the web (where dart:js is present)!'); -} diff --git a/spine-flutter/lib/web_ffi/modules/exceptions.dart b/spine-flutter/lib/web_ffi/modules/exceptions.dart deleted file mode 100755 index cd3eab906..000000000 --- a/spine-flutter/lib/web_ffi/modules/exceptions.dart +++ /dev/null @@ -1,17 +0,0 @@ -/// Occures if it's not possible to convert dart types to JavaScript types. -/// -/// This usually happens if a not allowed type is uses as a [NativeType]'s -/// type argument, or a not allowed return value of a [NativeFunction] is -/// used. -class MarshallingException implements Exception { - final dynamic message; - const MarshallingException([this.message]); - - MarshallingException.noAddress(Object o) : this('Expected a address (int) but found ${o.runtimeType}'); - - MarshallingException.typeMissmatch(Type t, Object o) - : this('Expected a type of $t but object has type ${o.runtimeType}'); - - @override - String toString() => new Exception(message).toString(); -} diff --git a/spine-flutter/lib/web_ffi/modules/memory.dart b/spine-flutter/lib/web_ffi/modules/memory.dart deleted file mode 100755 index ee08a0c18..000000000 --- a/spine-flutter/lib/web_ffi/modules/memory.dart +++ /dev/null @@ -1,123 +0,0 @@ -import 'dart:typed_data'; -import 'package:meta/meta.dart'; - -import '../ffi/utf8.dart'; -import 'module.dart'; -import '../ffi/types.dart'; -import '../internal/marshaller.dart'; -import '../web_ffi_meta.dart'; - -final Map sizeMap = {}; - -/// Must be called with each type that extends Opaque before -/// attemtping to use that type. -@extra -void registerOpaqueType() { - sizeMap[T] = sizeOf(); - registerNativeMarshallerOpaque(); -} - -void _registerType(int size) { - sizeMap[T] = size; - registerNativeMarshallerType(); -} - -/// Represents the native heap. -@extra -class Memory implements Allocator { - /// The endianess of data stored. - /// - /// The WebAssembly speficiation defines little endianess, so this is a constant. - static const Endian endianess = Endian.little; - - /// Must be called before working with `web_ffi` to initalize all type sizes. - /// - /// The optional parameter [pointerSizeBytes] can be used to adjust the size - /// of pointers. It defaults to `4` since WebAssembly usually uses 32 bit pointers. - /// If you want to use wasm64, set [pointerSizeBytes] to `8` to denote 64 bit pointers. - static void init([int pointerSizeBytes = 4]) { - _registerType(4); - _registerType(8); - _registerType(1); - _registerType(1); - _registerType(2); - _registerType(2); - _registerType(4); - _registerType(4); - _registerType(8); - _registerType(8); - _registerType(8); - _registerType(1); - _registerType(1); - _registerType(pointerSizeBytes); - _registerType(4); // int in C is typically 4 bytes (even on 64-bit) - _registerType(pointerSizeBytes); // size_t matches pointer size - _registerType(1); // bool/_Bool is 1 byte - _registerType(1); - _registerType(2); - _registerType(pointerSizeBytes); - registerNativeMarshallerType(); - registerNativeMarshallerType>(); - } - - /// The default [Memory] object to use. - /// - /// This field is null until it is either manually set to a [Memory] object, - /// or automatically set by [DynamicLibrary.fromModule]. - /// - /// This is most notably used when creating a pointer using [Pointer.fromAddress] - /// with no explicite memory to bind to given. - static Memory? global; - - /// Can be used to directly access the memory of this object. - /// - /// The value of this field should not be stored in a state variable, - /// since the returned buffer may change over time. - @doNotStore - ByteBuffer get buffer => _module.heap; - - final Module _module; - final Map _symbolsByName; - final Map _symbolsByAddress; - - Memory._(this._module) - : _symbolsByAddress = new Map.fromEntries(_module.exports.map>( - (WasmSymbol symbol) => new MapEntry(symbol.address, symbol))), - _symbolsByName = new Map.fromEntries(_module.exports.map>( - (WasmSymbol symbol) => new MapEntry(symbol.name, symbol))); - - @override - Pointer allocate(int byteCount, {int? alignment}) { - return new Pointer.fromAddress(_module.malloc(byteCount), this); - } - - @override - void free(Pointer pointer) { - _module.free(pointer.address); - } -} - -Memory createMemory(Module module) => new Memory._(module); - -WasmSymbol symbolByAddress(Memory m, int address) { - WasmSymbol? s = m._symbolsByAddress[address]; - if (s != null) { - return s; - } else { - throw new ArgumentError('Could not find symbol at $address!'); - } -} - -WasmSymbol symbolByName(Memory m, String name) { - WasmSymbol? s = m._symbolsByName[name]; - if (s != null) { - return s; - } else { - throw new ArgumentError('Could not find symbol $name!'); - } -} - -/// Used on [DynamicLibrary] creation to control if the therby newly created -/// [Memory] object should be registered as [Memory.global]. -@extra -enum MemoryRegisterMode { yes, no, onlyIfGlobalNotSet } diff --git a/spine-flutter/lib/web_ffi/modules/module.dart b/spine-flutter/lib/web_ffi/modules/module.dart deleted file mode 100755 index d9d6c360c..000000000 --- a/spine-flutter/lib/web_ffi/modules/module.dart +++ /dev/null @@ -1,107 +0,0 @@ -import 'dart:typed_data'; -import 'package:meta/meta.dart'; -import '../web_ffi_meta.dart'; - -/// Base class to interact with the WebAssembly. -/// -/// Currently, only [emscripten](https://emscripten.org) compiled WebAssembly is supported, -/// so the only concrete implementation if this class is [EmscriptenModule]. -/// -/// To support additional mechanisms/frameworks/compilers, create a subclass of -/// [Module]. -@extra -abstract class Module { - /// Provides access to the malloc function in WebAssembly. - /// - /// Allocates `size` bytes of memory and returns the corresponding - /// address. - /// - /// Memory allocated by this should be [free]d afterwards. - int malloc(int size); - - /// Provides access to the free function in WebAssembly. - /// - /// Frees the memory region at `pointer` that was previously - /// allocated with [malloc]. - void free(int pointer); - - /// Provides access to the [WebAssemblys memory](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) buffer. - /// - /// The actual [ByteBuffer] object returned by this getter is allowed to change; - /// It should not be cached in a state variable and is thus annotated with @[doNotStore]. - @doNotStore - ByteBuffer get heap; - - /// A list containing everything exported by the underlying - /// [WebAssembly instance](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance). - List get exports; -} - -/// Describes something exported by the WebAssembly. -@extra -@sealed -abstract class WasmSymbol { - /// The address of the exported thing. - final int address; - - /// The name of the exported thing. - final String name; - - const WasmSymbol({required this.address, required this.name}); - - @override - int get hashCode => toString().hashCode; - - @override - String toString() => '[address=$address\tname=$name]'; -} - -/// A global is a symbol exported by the WebAssembly, -/// that is not a function. -@extra -@sealed -class Global extends WasmSymbol { - const Global({required int address, required String name}) : super(address: address, name: name); - - @override - bool operator ==(Object other) { - if (other is Global) { - return name == other.name && address == other.address; - } else { - return false; - } - } -} - -/// Describes a function exported from WebAssembly. -@extra -@sealed -class FunctionDescription extends WasmSymbol { - /// The index of this function in the [WebAssembly table](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Table). - /// This is the same as its address. - int get tableIndex => address; - - /// The amount of arguments the underyling function has. - final int argumentCount; - - /// The actual function. - final Function function; - const FunctionDescription( - {required int tableIndex, required String name, required this.argumentCount, required this.function}) - : super(address: tableIndex, name: name); - - @override - int get hashCode => '$name$argumentCount$tableIndex'.hashCode; - - @override - bool operator ==(Object other) { - if (other is FunctionDescription) { - return argumentCount == other.argumentCount && name == other.name && tableIndex == other.tableIndex; - } else { - return false; - } - } - - @override - String toString() => '[tableIndex=$tableIndex\tname=$name\targumentCount=$argumentCount\tfunction=$function]'; -} diff --git a/spine-flutter/lib/web_ffi/modules/null_memory.dart b/spine-flutter/lib/web_ffi/modules/null_memory.dart deleted file mode 100755 index 74afec5f3..000000000 --- a/spine-flutter/lib/web_ffi/modules/null_memory.dart +++ /dev/null @@ -1,18 +0,0 @@ -import 'dart:typed_data'; -import 'memory.dart'; -import '../ffi/types.dart'; - -class NullMemory implements Memory { - @override - Pointer allocate(int byteCount, {int? alignment}) { - throw new UnsupportedError('Can not use the null memory to allocate space!'); - } - - @override - ByteBuffer get buffer => throw new UnsupportedError('The null memory has no buffer!'); - - @override - void free(Pointer pointer) { - throw new UnsupportedError('Can not use the null memory to free pointers!'); - } -} diff --git a/spine-flutter/lib/web_ffi/web_ffi.dart b/spine-flutter/lib/web_ffi/web_ffi.dart deleted file mode 100755 index 7f91452e3..000000000 --- a/spine-flutter/lib/web_ffi/web_ffi.dart +++ /dev/null @@ -1,7 +0,0 @@ -/// Provides mechanisms to use a [dart:ffi 2.12.0](https://api.dart.dev/stable/2.12.0/dart-ffi/dart-ffi-library.html) like API on the web but using [dart:js](https://api.dart.dev/stable/dart-js/dart-js-library.html). -/// While some things are missing, new things were added, identifiable by the @[extra] annotation. -library web_ffi; - -export './ffi/types.dart'; -export './ffi/extensions.dart'; -export './ffi/utf8.dart'; diff --git a/spine-flutter/lib/web_ffi/web_ffi_meta.dart b/spine-flutter/lib/web_ffi/web_ffi_meta.dart deleted file mode 100755 index 9491003c4..000000000 --- a/spine-flutter/lib/web_ffi/web_ffi_meta.dart +++ /dev/null @@ -1,4 +0,0 @@ -/// This library contains and explains the annotations for `web_ffi`. -library web_ffi_meta; - -export 'meta/meta.dart'; diff --git a/spine-flutter/lib/web_ffi/web_ffi_modules.dart b/spine-flutter/lib/web_ffi/web_ffi_modules.dart deleted file mode 100755 index b8b80f83b..000000000 --- a/spine-flutter/lib/web_ffi/web_ffi_modules.dart +++ /dev/null @@ -1,10 +0,0 @@ -/// Provides additional classes that are needed for web_ffi, -/// but are not present in [dart:ffi](https://api.dart.dev/stable/2.12.0/dart-ffi/dart-ffi-library.html). -library web_ffi_modules; - -export 'modules/exceptions.dart'; -export 'modules/module.dart'; -export 'modules/memory.dart' show registerOpaqueType, Memory, MemoryRegisterMode; - -export 'modules/emscripten/emscripten_module_stub.dart' - if (dart.library.js) 'modules/emscripten/emscripten_module.dart' show EmscriptenModule; diff --git a/spine-flutter/pubspec.yaml b/spine-flutter/pubspec.yaml index 642ad54f8..0766b4413 100644 --- a/spine-flutter/pubspec.yaml +++ b/spine-flutter/pubspec.yaml @@ -20,6 +20,7 @@ dependencies: http: ^1.1.0 path: ^1.8.2 crypto: ^3.0.3 + wasm_ffi: ^2.0.7 dev_dependencies: ffigen: ^10.0.0 diff --git a/spine-flutter/test/pubspec.lock b/spine-flutter/test/pubspec.lock index 99ec5c6da..48d5305a5 100644 --- a/spine-flutter/test/pubspec.lock +++ b/spine-flutter/test/pubspec.lock @@ -329,7 +329,7 @@ packages: path: ".." relative: true source: path - version: "4.2.36" + version: "4.3.0" stack_trace: dependency: transitive description: @@ -426,14 +426,6 @@ packages: url: "https://pub.dev" source: hosted version: "1.1.1" - web_ffi_fork: - dependency: transitive - description: - name: web_ffi_fork - sha256: "557b3008bb3c8547ee63eac6e53c0ebebb443da9d7558b3f1b98e1ed59989a11" - url: "https://pub.dev" - source: hosted - version: "0.7.5" web_socket: dependency: transitive description: