diff --git a/lib/src/eval/shared/stdlib/convert.dart b/lib/src/eval/shared/stdlib/convert.dart index 9ae5d7a..6eb89b2 100644 --- a/lib/src/eval/shared/stdlib/convert.dart +++ b/lib/src/eval/shared/stdlib/convert.dart @@ -1,5 +1,6 @@ import 'package:dart_eval/dart_eval.dart'; import 'package:dart_eval/dart_eval_bridge.dart'; +import 'package:dart_eval/src/eval/shared/stdlib/convert/base64.dart'; import 'package:dart_eval/src/eval/shared/stdlib/convert/codec.dart'; import 'package:dart_eval/src/eval/shared/stdlib/convert/converter.dart'; import 'package:dart_eval/src/eval/shared/stdlib/convert/encoding.dart'; @@ -9,6 +10,8 @@ import 'package:dart_eval/src/eval/shared/stdlib/convert/utf.dart'; const convertSource = ''' final utf8 = Utf8Codec(); final json = JsonCodec(); +final Base64Codec base64Url = Base64Codec.urlSafe(); +final base64 = Base64Codec(); '''; /// [EvalPlugin] for the `dart:convert` library @@ -23,6 +26,9 @@ class DartConvertPlugin implements EvalPlugin { registry.defineBridgeClass($Encoding.$declaration); registry.defineBridgeClass($Utf8Decoder.$declaration); registry.defineBridgeClass($Utf8Codec.$declaration); + registry.defineBridgeClass($Base64Encoder.$declaration); + registry.defineBridgeClass($Base64Decoder.$declaration); + registry.defineBridgeClass($Base64Codec.$declaration); registry.defineBridgeClass($JsonDecoder.$declaration); registry.defineBridgeClass($JsonEncoder.$declaration); registry.defineBridgeClass($JsonCodec.$declaration); @@ -34,6 +40,7 @@ class DartConvertPlugin implements EvalPlugin { runtime.registerBridgeFunc( 'dart:convert', 'Utf8Decoder.', $Utf8Decoder.$new); runtime.registerBridgeFunc('dart:convert', 'Utf8Codec.', $Utf8Codec.$new); + $Base64Codec.configureForRuntime(runtime); runtime.registerBridgeFunc( 'dart:convert', 'JsonDecoder.', $JsonDecoder.$new); runtime.registerBridgeFunc( diff --git a/lib/src/eval/shared/stdlib/convert/base64.dart b/lib/src/eval/shared/stdlib/convert/base64.dart new file mode 100644 index 0000000..91edca1 --- /dev/null +++ b/lib/src/eval/shared/stdlib/convert/base64.dart @@ -0,0 +1,237 @@ +import 'dart:convert'; +import 'package:dart_eval/dart_eval.dart'; +import 'package:dart_eval/dart_eval_bridge.dart'; +import 'package:dart_eval/src/eval/shared/stdlib/convert/codec.dart'; +import 'package:dart_eval/src/eval/shared/stdlib/convert/converter.dart'; +import 'package:dart_eval/stdlib/core.dart'; + +/// dart_eval wrapper for [Base64Decoder] +class $Base64Decoder implements $Instance { + /// Compile-time bridge type reference for [$Base64Decoder] + static const $type = BridgeTypeRef(ConvertTypes.base64Decoder); + + /// Compile-time bridge class declaration for [$Base64Decoder] + static const $declaration = BridgeClassDef( + BridgeClassType($type, + $extends: BridgeTypeRef(ConvertTypes.converter, [ + BridgeTypeRef(CoreTypes.string), + BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.int)]), + ])), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type))) + }, + methods: {}, + getters: {}, + setters: {}, + fields: {}, + wrap: true); + + /// Wrap a [Base64Decoder] in a [$Base64Decoder]. + $Base64Decoder.wrap(this.$value); + static $Base64Decoder $new( + Runtime runtime, $Value? target, List<$Value?> args) { + return $Base64Decoder.wrap(Base64Decoder()); + } + + late final $Instance _superclass = $Converter.wrap($value); + @override + final Base64Decoder $value; + @override + get $reified => $value; + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + default: + return _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); +} + +/// dart_eval wrapper for [Base64Encoder] +class $Base64Encoder implements $Instance { + /// Compile-time bridge type reference for [$Base64Encoder] + static const $type = BridgeTypeRef(ConvertTypes.base64Encoder); + + /// Compile-time bridge class declaration for [$Base64Encoder] + static const $declaration = BridgeClassDef( + BridgeClassType($type, + $extends: BridgeTypeRef(ConvertTypes.converter, [ + BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.int)]), + BridgeTypeRef(CoreTypes.string), + ])), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type))) + }, + methods: {}, + getters: {}, + setters: {}, + fields: {}, + wrap: true); + + /// Wrap a [Base64Encoder] in a [$Base64Encoder]. + $Base64Encoder.wrap(this.$value); + static $Base64Encoder $new( + Runtime runtime, $Value? target, List<$Value?> args) { + return $Base64Encoder.wrap(Base64Encoder()); + } + + late final $Instance _superclass = $Converter.wrap($value); + @override + final Base64Encoder $value; + @override + get $reified => $value; + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + default: + return _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); +} + +/// dart_eval wrapper for [Base64Codec] +class $Base64Codec implements $Instance { + /// Compile-time bridge type reference for [$Base64Codec] + static const $type = BridgeTypeRef(ConvertTypes.base64Codec); + + /// Compile-time bridge class declaration for [$Base64Codec] + static const $declaration = BridgeClassDef( + BridgeClassType($type, $extends: BridgeTypeRef(ConvertTypes.encoding)), + constructors: { + '': BridgeConstructorDef( + BridgeFunctionDef(returns: BridgeTypeAnnotation($type))), + 'urlSafe': BridgeConstructorDef( + BridgeFunctionDef( + returns: + BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.base64Codec)), + ), + isFactory: true), + }, + methods: { + 'encode': BridgeMethodDef(BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'input', + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])), + false), + ])), + 'decode': BridgeMethodDef(BridgeFunctionDef( + returns: BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])), + params: [ + BridgeParameter('input', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + ])), + }, + getters: { + 'decoder': BridgeMethodDef(BridgeFunctionDef( + returns: BridgeTypeAnnotation( + BridgeTypeRef(ConvertTypes.base64Decoder)))), + 'encoder': BridgeMethodDef(BridgeFunctionDef( + returns: BridgeTypeAnnotation( + BridgeTypeRef(ConvertTypes.base64Encoder)))), + }, + setters: {}, + fields: {}, + wrap: true); + + /// Wrap a [Base64Codec] in a [$Base64Codec]. + $Base64Codec.wrap(this.$value); + static $Base64Codec $new( + Runtime runtime, $Value? target, List<$Value?> args) { + return $Base64Codec.wrap(Base64Codec()); + } + + static void configureForRuntime(Runtime runtime) { + runtime.registerBridgeFunc( + 'dart:convert', 'Base64Encoder.', $Base64Encoder.$new); + runtime.registerBridgeFunc( + 'dart:convert', 'Base64Decoder.', $Base64Decoder.$new); + runtime.registerBridgeFunc( + 'dart:convert', 'Base64Codec.', $Base64Codec.$new); + runtime.registerBridgeFunc('dart:convert', 'Base64Codec.urlSafe', _urlSafe); + } + + late final $Instance _superclass = $Codec.wrap($value); + @override + final Base64Codec $value; + @override + get $reified => $value; + @override + $Value? $getProperty(Runtime runtime, String identifier) { + switch (identifier) { + case 'decoder': + return $Base64Decoder.wrap($value.decoder); + case 'encoder': + return $Base64Encoder.wrap($value.encoder); + case 'encode': + return __encode; + case 'decode': + return __decode; + default: + return _superclass.$getProperty(runtime, identifier); + } + } + + static const $Function __encode = $Function(_encode); + static $Value? _encode( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + final input = (args[0]!.$value as List) + .map((e) => (e is $Value ? e.$reified : e) as int) + .toList(); + return $String((target as $Base64Codec).$value.encode(input)); + } + + static const $Function __decode = $Function(_decode); + static $Value? _decode( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + return $List.wrap((target as $Base64Codec) + .$value + .decode(args[0]!.$value) + .map((e) => $int(e)) + .toList()); + } + + static $Value? _urlSafe( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + return $Base64Codec.wrap(Base64Codec.urlSafe()); + } + + @override + void $setProperty(Runtime runtime, String identifier, $Value value) { + switch (identifier) { + default: + return _superclass.$setProperty(runtime, identifier, value); + } + } + + @override + int $getRuntimeType(Runtime runtime) => + runtime.lookupType(ConvertTypes.base64Codec); +} diff --git a/lib/src/eval/shared/stdlib/convert/utf.dart b/lib/src/eval/shared/stdlib/convert/utf.dart index abdfdc2..4cd80b2 100644 --- a/lib/src/eval/shared/stdlib/convert/utf.dart +++ b/lib/src/eval/shared/stdlib/convert/utf.dart @@ -86,14 +86,32 @@ class $Utf8Codec implements $Instance { BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), true) ])) }, - methods: {}, + methods: { + 'encode': BridgeMethodDef(BridgeFunctionDef( + returns: BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])), + params: [ + BridgeParameter('input', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), false), + ])), + 'decode': BridgeMethodDef(BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'codeUnits', + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])), + false), + ], + namedParams: [ + BridgeParameter('allowMalformed', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), true) + ])), + }, getters: { 'decoder': BridgeMethodDef(BridgeFunctionDef( returns: - BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.utf8Decoder, [ - BridgeTypeRef(CoreTypes.list, [BridgeTypeRef(CoreTypes.int)]), - BridgeTypeRef(CoreTypes.string), - ])))), + BridgeTypeAnnotation(BridgeTypeRef(ConvertTypes.utf8Decoder)))), }, setters: {}, fields: {}, @@ -120,11 +138,36 @@ class $Utf8Codec implements $Instance { switch (identifier) { case 'decoder': return $Utf8Decoder.wrap($value.decoder); + case 'decode': + return __decode; + case 'encode': + return __encode; default: return _superclass.$getProperty(runtime, identifier); } } + static const $Function __decode = $Function(_decode); + static $Value? _decode( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + final codeUnits = (args[0]!.$value as List) + .map((e) => (e is $Value ? e.$reified : e) as int) + .toList(); + return $String((target as $Utf8Codec) + .$value + .decode(codeUnits, allowMalformed: args[1]?.$value)); + } + + static const $Function __encode = $Function(_encode); + static $Value? _encode( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + return $List.wrap((target as $Utf8Codec) + .$value + .encode(args[0]!.$value) + .map((e) => $int(e)) + .toList()); + } + @override void $setProperty(Runtime runtime, String identifier, $Value value) { switch (identifier) { diff --git a/lib/src/eval/shared/stdlib/core/base.dart b/lib/src/eval/shared/stdlib/core/base.dart index d09f215..0f25065 100644 --- a/lib/src/eval/shared/stdlib/core/base.dart +++ b/lib/src/eval/shared/stdlib/core/base.dart @@ -140,6 +140,24 @@ class $String implements $Instance { BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), false) ]), isFactory: true), + 'fromCharCodes': BridgeConstructorDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'charCodes', + BridgeTypeAnnotation(BridgeTypeRef( + BridgeTypeSpec('dart:core', 'Iterable'))), + false), + BridgeParameter('start', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int)), true), + BridgeParameter( + 'end', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.int), + nullable: true), + true), + ]), + isFactory: true), }, methods: { // Other string methods defined in builtins.dart @@ -174,6 +192,8 @@ class $String implements $Instance { static void configureForRuntime(Runtime runtime) { runtime.registerBridgeFunc( 'dart:core', 'String.fromCharCode', _fromCharCode); + runtime.registerBridgeFunc( + 'dart:core', 'String.fromCharCodes', _fromCharCodes); } static $Value? _fromCharCode( @@ -181,6 +201,17 @@ class $String implements $Instance { return $String(String.fromCharCode(args[0]?.$value)); } + static $Value? _fromCharCodes( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + final charCodes = (args[0]!.$value as Iterable) + .map((e) => (e is $Value ? e.$reified : e) as int); + int? end; + try { + end = args[2]?.$value as int?; + } catch (_) {} + return $String(String.fromCharCodes(charCodes, args[1]?.$value ?? 0, end)); + } + @override $Value? $getProperty(Runtime runtime, String identifier) { switch (identifier) { @@ -197,7 +228,7 @@ class $String implements $Instance { case 'codeUnitAt': return __codeUnitAt; case 'codeUnits': - return wrapList($value.codeUnits, (e) => $int(e)); + return wrapList($value.codeUnits, (e) => $int(e)); case 'compareTo': return __compareTo; case 'contains': diff --git a/lib/src/eval/shared/stdlib/core/uri.dart b/lib/src/eval/shared/stdlib/core/uri.dart index 530bb40..1cd6c60 100644 --- a/lib/src/eval/shared/stdlib/core/uri.dart +++ b/lib/src/eval/shared/stdlib/core/uri.dart @@ -1,3 +1,5 @@ +import 'dart:convert'; + import 'package:dart_eval/dart_eval.dart'; import 'package:dart_eval/dart_eval_bridge.dart'; import 'package:dart_eval/src/eval/utils/wap_helper.dart'; @@ -11,6 +13,28 @@ class $Uri implements $Instance { runtime.registerBridgeFunc('dart:core', 'Uri.tryParse', $tryParse); runtime.registerBridgeFunc('dart:core', 'Uri.encodeFull', $encodeFull); runtime.registerBridgeFunc('dart:core', 'Uri.decodeFull', $decodeFull); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.encodeComponent', $encodeComponent); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.decodeComponent', $decodeComponent); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.decodeQueryComponent', $decodeQueryComponent); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.encodeQueryComponent', $encodeQueryComponent); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.dataFromBytes', $dataFromBytes); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.dataFromString', $dataFromString); + runtime.registerBridgeFunc('dart:core', 'Uri.directory', $directory); + runtime.registerBridgeFunc('dart:core', 'Uri.file', $file); + runtime.registerBridgeFunc('dart:core', 'Uri.http', $http); + runtime.registerBridgeFunc('dart:core', 'Uri.https', $https); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.parseIPv4Address', $parseIPv4Address); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.parseIPv6Address', $parseIPv6Address); + runtime.registerBridgeFunc( + 'dart:core', 'Uri.splitQueryString', $splitQueryString); } /// Bridge type spec for [$Uri] @@ -59,6 +83,284 @@ class $Uri implements $Instance { ], namedParams: []), isStatic: true), + 'encodeComponent': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'component', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false) + ], + namedParams: []), + isStatic: true), + 'decodeComponent': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'encodedComponent', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false) + ], + namedParams: []), + isStatic: true), + 'decodeQueryComponent': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'encodedComponent', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: [ + BridgeParameter( + 'encoding', + BridgeTypeAnnotation( + BridgeTypeRef(ConvertTypes.encoding)), + true) + ]), + isStatic: true), + 'encodeQueryComponent': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'component', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: [ + BridgeParameter( + 'encoding', + BridgeTypeAnnotation( + BridgeTypeRef(ConvertTypes.encoding)), + true) + ]), + isStatic: true), + 'dataFromBytes': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'bytes', + BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])), + false), + ], + namedParams: [ + BridgeParameter( + 'mimeType', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + true), + BridgeParameter( + 'parameters', + BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.map, [ + BridgeTypeRef(CoreTypes.string), + BridgeTypeRef(CoreTypes.string) + ]), + ), + true), + BridgeParameter( + 'percentEncoded', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), + true), + ]), + isStatic: true), + 'dataFromString': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'content', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: [ + BridgeParameter( + 'mimeType', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + true), + BridgeParameter( + 'parameters', + BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.map, [ + BridgeTypeRef(CoreTypes.string), + BridgeTypeRef(CoreTypes.string) + ]), + nullable: true), + true), + BridgeParameter( + 'base64', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), + true), + ]), + isStatic: true), + 'directory': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'path', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: [ + BridgeParameter('windows', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), true) + ]), + isStatic: true), + 'file': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'path', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: [ + BridgeParameter('windows', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.bool)), true) + ]), + isStatic: true), + 'http': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'authority', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + BridgeParameter( + 'unencodedPath', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + true), + BridgeParameter( + 'queryParameters', + BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.map, [ + BridgeTypeRef(CoreTypes.string), + BridgeTypeRef(CoreTypes.dynamic) + ]), + nullable: true), + true), + ], + namedParams: []), + isStatic: true), + 'https': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + params: [ + BridgeParameter( + 'authority', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + BridgeParameter( + 'unencodedPath', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + true), + BridgeParameter( + 'queryParameters', + BridgeTypeAnnotation( + BridgeTypeRef(CoreTypes.map, [ + BridgeTypeRef(CoreTypes.string), + BridgeTypeRef(CoreTypes.dynamic) + ]), + nullable: true), + true), + ], + namedParams: []), + isStatic: true), + 'parseIPv4Address': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])), + params: [ + BridgeParameter( + 'host', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: []), + isStatic: true), + 'parseIPv6Address': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef( + CoreTypes.list, [BridgeTypeRef(CoreTypes.int)])), + params: [ + BridgeParameter( + 'host', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + BridgeParameter( + 'start', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + true), + BridgeParameter( + 'end', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string), + nullable: true), + true), + ], + namedParams: []), + isStatic: true), + 'splitQueryString': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.map, [ + BridgeTypeRef(CoreTypes.string), + BridgeTypeRef(CoreTypes.string) + ])), + params: [ + BridgeParameter( + 'query', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: [ + BridgeParameter( + 'encoding', + BridgeTypeAnnotation( + BridgeTypeRef(ConvertTypes.encoding)), + true) + ]), + isStatic: true), + 'resolve': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), + params: [ + BridgeParameter( + 'reference', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: []), + isStatic: true), + 'normalizePath': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), + params: [], + namedParams: []), + isStatic: true), + 'removeFragment': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), + params: [], + namedParams: []), + isStatic: true), + 'resolveUri': BridgeMethodDef( + BridgeFunctionDef( + returns: BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.uri)), + params: [ + BridgeParameter( + 'reference', + BridgeTypeAnnotation(BridgeTypeRef(CoreTypes.string)), + false), + ], + namedParams: []), + isStatic: true), }, getters: { 'scheme': BridgeMethodDef(BridgeFunctionDef( @@ -138,15 +440,15 @@ class $Uri implements $Instance { case 'fragment': return $String($value.fragment); case 'pathSegments': - return wrapList($value.pathSegments, (e) => $String(e)); + return wrapList($value.pathSegments, (e) => $String(e)); case 'queryParameters': - return wrapMap($value.queryParameters, + return wrapMap($value.queryParameters, (key, value) => MapEntry($String(key), $String(value))); case 'queryParametersAll': - return wrapMap( + return wrapMap>( $value.queryParametersAll, - (key, value) => - MapEntry($String(key), wrapList(value, (e) => $String(e)))); + (key, value) => MapEntry( + $String(key), wrapList(value, (e) => $String(e)))); case 'isAbsolute': return $bool($value.isAbsolute); case 'hasScheme': @@ -165,6 +467,14 @@ class $Uri implements $Instance { return $bool($value.hasAbsolutePath); case 'origin': return $String($value.origin); + case 'resolve': + return __resolve; + case 'normalizePath': + return __normalizePath; + case 'removeFragment': + return __removeFragment; + case 'resolveUri': + return __resolveUri; default: return _superclass.$getProperty(runtime, identifier); @@ -176,6 +486,30 @@ class $Uri implements $Instance { return _superclass.$setProperty(runtime, identifier, value); } + static const $Function __resolve = $Function(_resolve); + static $Value? _resolve( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + return $Uri.wrap((target as $Uri).$value.resolve(args[0]!.$value)); + } + + static const $Function __normalizePath = $Function(_normalizePath); + static $Value? _normalizePath( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + return $Uri.wrap((target as $Uri).$value.normalizePath()); + } + + static const $Function __removeFragment = $Function(_removeFragment); + static $Value? _removeFragment( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + return $Uri.wrap((target as $Uri).$value.removeFragment()); + } + + static const $Function __resolveUri = $Function(_resolveUri); + static $Value? _resolveUri( + final Runtime runtime, final $Value? target, final List<$Value?> args) { + return $Uri.wrap((target as $Uri).$value.resolveUri(args[0]!.$value)); + } + static $Value? $parse(Runtime runtime, $Value? target, List<$Value?> args) { final uri = args[0]!.$value as String; return $Uri.wrap(Uri.parse(uri)); @@ -200,6 +534,98 @@ class $Uri implements $Instance { return $String(Uri.decodeFull(uri)); } + static $Value? $encodeComponent( + Runtime runtime, $Value? target, List<$Value?> args) { + return $String(Uri.encodeComponent(args[0]!.$value)); + } + + static $Value? $decodeComponent( + Runtime runtime, $Value? target, List<$Value?> args) { + return $String(Uri.decodeComponent(args[0]!.$value)); + } + + static $Value? $decodeQueryComponent( + Runtime runtime, $Value? target, List<$Value?> args) { + return $String(Uri.decodeQueryComponent(args[0]!.$value, + encoding: (args[1]?.$value as Encoding?) ?? utf8)); + } + + static $Value? $encodeQueryComponent( + Runtime runtime, $Value? target, List<$Value?> args) { + return $String(Uri.encodeQueryComponent(args[0]!.$value, + encoding: (args[1]?.$value as Encoding?) ?? utf8)); + } + + static $Value? $dataFromBytes( + Runtime runtime, $Value? target, List<$Value?> args) { + final bytes = (args[0]!.$value as List) + .map((e) => (e is $Value ? e.$reified : e) as int) + .toList(); + final parameters = (args[2]?.$value as Map?)?.map((key, value) => + MapEntry(key.$reified.toString(), value.$reified.toString())); + return $Uri.wrap(Uri.dataFromBytes(bytes, + mimeType: args[1]?.$value ?? "application/octet-stream", + parameters: parameters, + percentEncoded: args[3]?.$value ?? false)); + } + + static $Value? $dataFromString( + Runtime runtime, $Value? target, List<$Value?> args) { + final parameters = (args[2]?.$value as Map?)?.map((key, value) => + MapEntry(key.$reified.toString(), value.$reified.toString())); + return $Uri.wrap(Uri.dataFromString(args[0]!.$value, + mimeType: args[1]?.$value ?? "application/octet-stream", + parameters: parameters, + base64: args[3]?.$value ?? false)); + } + + static $Value? $directory( + Runtime runtime, $Value? target, List<$Value?> args) { + return $Uri.wrap(Uri.directory(args[0]!.$value, + windows: (args[1]?.$value as bool?) ?? false)); + } + + static $Value? $file(Runtime runtime, $Value? target, List<$Value?> args) { + return $Uri.wrap(Uri.file(args[0]!.$value, + windows: (args[1]?.$value as bool?) ?? false)); + } + + static $Value? $http(Runtime runtime, $Value? target, List<$Value?> args) { + final queryParameters = (args[2]?.$value as Map?)?.map( + (key, value) => MapEntry(key.$reified.toString(), value.$reified)); + return $Uri.wrap( + Uri.http(args[0]!.$value, args[1]?.$value ?? "", queryParameters)); + } + + static $Value? $https(Runtime runtime, $Value? target, List<$Value?> args) { + final queryParameters = (args[2]?.$value as Map?)?.map( + (key, value) => MapEntry(key.$reified.toString(), value.$reified)); + return $Uri.wrap( + Uri.https(args[0]!.$value, args[1]?.$value ?? "", queryParameters)); + } + + static $Value? $parseIPv4Address( + Runtime runtime, $Value? target, List<$Value?> args) { + return $List.wrap( + Uri.parseIPv4Address(args[0]!.$value).map((e) => $int(e)).toList()); + } + + static $Value? $parseIPv6Address( + Runtime runtime, $Value? target, List<$Value?> args) { + return $List.wrap(Uri.parseIPv6Address( + args[0]!.$value, args[1]?.$value ?? 0, args[2]?.$value) + .map((e) => $int(e)) + .toList()); + } + + static $Value? $splitQueryString( + Runtime runtime, $Value? target, List<$Value?> args) { + return wrapMap( + Uri.splitQueryString(args[0]!.$value, + encoding: (args[1]?.$value as Encoding?) ?? utf8), + (key, value) => MapEntry($String(key), $String(value))); + } + @override int $getRuntimeType(Runtime runtime) => runtime.lookupType($type.spec!); diff --git a/test/convert_test.dart b/test/convert_test.dart index bccd3ff..5b67def 100644 --- a/test/convert_test.dart +++ b/test/convert_test.dart @@ -1,6 +1,7 @@ @TestOn('vm') import 'package:dart_eval/dart_eval.dart'; +import 'package:dart_eval/dart_eval_bridge.dart'; import 'package:test/test.dart'; void main() { @@ -78,5 +79,141 @@ void main() { ), 1); }); + test('utf8.encode()', () async { + final runtime = compiler.compileWriteAndLoad({ + 'example': { + 'main.dart': ''' + import 'dart:convert'; + + List main() { + return utf8.encode("Hello world"); + } + ''' + } + }); + + expect( + runtime + .executeLib( + 'package:example/main.dart', + 'main', + ) + .map((e) => (e is $Value ? e.$reified : e) as int) + .toList(), + [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]); + }); + + test('utf8.decode()', () async { + final runtime = compiler.compileWriteAndLoad({ + 'example': { + 'main.dart': ''' + import 'dart:convert'; + + String main() { + return utf8.decode([72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]); + } + ''' + } + }); + + expect( + runtime + .executeLib( + 'package:example/main.dart', + 'main', + ) + .$reified, + "Hello world"); + }); + test('base64.encode()', () async { + final runtime = compiler.compileWriteAndLoad({ + 'example': { + 'main.dart': ''' + import 'dart:convert'; + + String main() { + return base64.encode([52, 149, 126]); + } + ''' + } + }); + + expect( + (runtime.executeLib( + 'package:example/main.dart', + 'main', + ) as $Value) + .$reified, + 'NJV+'); + }); + + test('base64.decode()', () async { + final runtime = compiler.compileWriteAndLoad({ + 'example': { + 'main.dart': ''' + import 'dart:convert'; + + List main() { + return base64.decode("SGVsbG8gd29ybGQ="); + } + ''' + } + }); + + expect( + runtime + .executeLib( + 'package:example/main.dart', + 'main', + ) + .map((e) => (e is $Value ? e.$reified : e) as int) + .toList(), + [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]); + }); + test('base64Url.encode()', () async { + final runtime = compiler.compileWriteAndLoad({ + 'example': { + 'main.dart': ''' + import 'dart:convert'; + + String main() { + return base64Url.encode([52, 149, 126]); + } + ''' + } + }); + + expect( + (runtime.executeLib( + 'package:example/main.dart', + 'main', + ) as $Value) + .$reified, + 'NJV-'); + }); + + test('base64Url.decode()', () async { + final runtime = compiler.compileWriteAndLoad({ + 'example': { + 'main.dart': ''' + import 'dart:convert'; + + List main() { + return base64Url.decode("SGVsbG8gd29ybGQ="); + } + ''' + } + }); + + expect( + runtime + .executeLib( + 'package:example/main.dart', + 'main', + ) + .map((e) => (e is $Value ? e.$reified : e) as int) + .toList(), + [72, 101, 108, 108, 111, 32, 119, 111, 114, 108, 100]); + }); }); }