| // Copyright (c) 2017, Anatoly Pulyaevskiy. All rights reserved. Use of this source code |
| // is governed by a BSD-style license that can be found in the LICENSE file. |
| |
| /// Utility functions for Dart <> JS interoperability. |
| @JS() |
| library node_interop.util; |
| |
| import 'dart:async'; |
| import 'dart:js'; |
| |
| import 'package:js/js.dart'; |
| import 'package:js/js_util.dart' as js_util; |
| |
| import 'node.dart'; |
| |
| export 'package:js/js_util.dart' hide jsify; |
| |
| Util get util => _util ??= require('util'); |
| Util _util; |
| |
| @JS() |
| @anonymous |
| abstract class Util { |
| /// Possible signatures: |
| /// |
| /// inspect(object[, options]) |
| /// inspect(object[, showHidden[, depth[, colors]]]) |
| external dynamic inspect(object, [arg1, arg2, arg3]); |
| } |
| |
| /// Returns Dart representation from JS Object. |
| /// |
| /// Basic types (`num`, `bool`, `String`) are returned as-is. JS arrays |
| /// are converted into `List` instances. JS objects are converted into |
| /// `Map` instances. Both arrays and objects are traversed recursively |
| /// converting nested values. |
| /// |
| /// Converting JS objects always results in a `Map<String, dynamic>` meaning |
| /// even if original object had an integer key set, it will be converted into |
| /// a `String`. This is different from JS semantics where you are allowed to |
| /// access a key by passing its int value, e.g. `obj[1]` would work in JS, |
| /// but fail in Dart. |
| /// |
| /// See also: |
| /// - [jsify] |
| T dartify<T>(Object jsObject) { |
| if (_isBasicType(jsObject)) { |
| return jsObject as T; |
| } |
| |
| if (jsObject is List) { |
| return jsObject.map(dartify).toList() as T; |
| } |
| |
| var keys = objectKeys(jsObject); |
| var result = new Map<String, dynamic>(); |
| for (var key in keys) { |
| result[key] = dartify(js_util.getProperty(jsObject, key)); |
| } |
| |
| return result as T; |
| } |
| |
| /// Returns the JS representation from Dart Object. |
| /// |
| /// This function is identical to the one from 'dart:js_util' with only |
| /// difference that it handles basic types ([String], [num], [bool] and [null]. |
| /// |
| /// See also: |
| /// - [dartify] |
| dynamic jsify(Object dartObject) { |
| if (_isBasicType(dartObject)) { |
| return dartObject; |
| } |
| |
| return js_util.jsify(dartObject); |
| } |
| |
| /// Returns `true` if the [value] is a very basic built-in type - e.g. |
| /// [null], [num], [bool] or [String]. It returns `false` in the other case. |
| bool _isBasicType(value) { |
| if (value == null || value is num || value is bool || value is String) { |
| return true; |
| } |
| return false; |
| } |
| |
| /// Creates Dart `Future` which completes when [promise] is resolved or |
| /// rejected. |
| /// |
| /// See also: |
| /// - [futureToPromise] |
| Future<T> promiseToFuture<T>(Promise promise) { |
| var completer = new Completer<T>.sync(); |
| promise.then(allowInterop((value) { |
| completer.complete(value); |
| }), allowInterop((error) { |
| completer.completeError(error); |
| })); |
| return completer.future; |
| } |
| |
| /// Creates JS `Promise` which is resolved when [future] completes. |
| /// |
| /// See also: |
| /// - [promiseToFuture] |
| Promise futureToPromise<T>(Future<T> future) { |
| return new Promise(allowInterop((Function resolve, Function reject) { |
| future.then(resolve, onError: reject); |
| })); |
| } |