最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Getting an arbitrary property from a JavaScript object in Dart - Stack Overflow

programmeradmin1浏览0评论

Edit: Here is a minimal project that illustrates my issue. You can see the error described by serving it to the browser: pub get and then either pub serve (dartium) or pub build --mode=debug (other browsers).

How can I access an arbitrary JavaScript property from Dart through a JsObjectImpl? I am using the ace.js library with an interop to Dart that I've adapted from a typescript interface, and the method I am calling returns a plain javascript object with key-value pairs.

Dart gives me a JsObjectImpl, which cannot be casted to a Map or a JsObject, both of which have [] accessors. It confusingly seems to inherit from the deprecated JSObject (note the 's' is capitalized in the latter) which does not have the [] accessor, so I can't get the data out.

Some error messages:

  1. When attempting a cast from JsObjectImpl to JsObject:
    ORIGINAL EXCEPTION: type 'JSObjectImpl' is not a subtype of type 'JsObject' of 'obj' where JSObjectImpl is from dart:js JsObject is from dart:js. I get a similar message when using Map as well.

  2. Looking at the object in the debugger, I can frustratingly see the property in JS view but not in the Dart object:

    The 4: Object is the data I want.

Edit: Here is a minimal project that illustrates my issue. You can see the error described by serving it to the browser: pub get and then either pub serve (dartium) or pub build --mode=debug (other browsers).

How can I access an arbitrary JavaScript property from Dart through a JsObjectImpl? I am using the ace.js library with an interop to Dart that I've adapted from a typescript interface, and the method I am calling returns a plain javascript object with key-value pairs.

Dart gives me a JsObjectImpl, which cannot be casted to a Map or a JsObject, both of which have [] accessors. It confusingly seems to inherit from the deprecated JSObject (note the 's' is capitalized in the latter) which does not have the [] accessor, so I can't get the data out.

Some error messages:

  1. When attempting a cast from JsObjectImpl to JsObject:
    ORIGINAL EXCEPTION: type 'JSObjectImpl' is not a subtype of type 'JsObject' of 'obj' where JSObjectImpl is from dart:js JsObject is from dart:js. I get a similar message when using Map as well.

  2. Looking at the object in the debugger, I can frustratingly see the property in JS view but not in the Dart object:

    The 4: Object is the data I want.

Share Improve this question edited Dec 22, 2016 at 20:10 ahirschberg asked Dec 21, 2016 at 23:50 ahirschbergahirschberg 1301 silver badge7 bronze badges 7
  • 1 can you create a small example which demonstrates this issue? It'll be easier to help if there's something to debug – Kul Commented Dec 22, 2016 at 12:23
  • preferred using dartpad.dartlang – Günter Zöchbauer Commented Dec 22, 2016 at 17:01
  • 1 pub.dartlang/packages/js is now a better option than dart:js for dart-js-interop – Günter Zöchbauer Commented Dec 22, 2016 at 17:02
  • 1 Just importing another package is not enough. Read the readme of the package pub.dartlang/packages/js about how to use it. – Günter Zöchbauer Commented Dec 22, 2016 at 20:22
  • 1 I'll help you out - let me just clone your package. – matanlurey Commented Dec 22, 2016 at 20:25
 |  Show 2 more ments

2 Answers 2

Reset to default 10

Ok, this was a fun one, happy holidays :)

It looks like Map is not a supported auto-conversion for package:js. So a couple of things:

  1. Filed https://github./dart-lang/sdk/issues/28194
  2. Sent your a PR introducing a workaround

For interested parties, we can use the browser-native Object.keys:

@JS()
library example;

import 'package:js/js.dart';

/// A workaround to converting an object from JS to a Dart Map.
Map jsToMap(jsObject) {
  return new Map.fromIterable(
    _getKeysOfObject(jsObject),
    value: (key) => getProperty(jsObject, key),
  );
}

// Both of these interfaces exist to call `Object.keys` from Dart.
//
// But you don't use them directly. Just see `jsToMap`.
@JS('Object.keys')
external List<String> _getKeysOfObject(jsObject);

And call it once we have an arbitrary JavaScript object:

var properties = jsToMap(toy.getData());
print(properties);

I had to modify @matanlurey solution so it works on dart 2.12 and is recursive.

import 'dart:js';

/// A workaround to deep-converting an object from JS to a Dart Object.
Object jsToDart(jsObject) {
  if (jsObject is JsArray || jsObject is Iterable) {
    return jsObject.map(jsToDart).toList();
  }
  if (jsObject is JsObject) {
    return Map.fromIterable(
      getObjectKeys(jsObject),
      value: (key) => jsToDart(jsObject[key]),
    );
  }
  return jsObject;
}

List<String> getObjectKeys(JsObject object) => context['Object']
    .callMethod('getOwnPropertyNames', [object])
    .toList()
    .cast<String>();
发布评论

评论列表(0)

  1. 暂无评论