-
Notifications
You must be signed in to change notification settings - Fork 1.7k
js-interop:accessing anonymous objects #26386
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
You can't use Map as argument or return value. You can look at #25053 (comment) to have an example of how to create arbitrary js objects (aka. js map). |
Does that mean I will also need to use Perhaps if there were some way to mixin helper functions to the |
I never tried a mixin with a |
I couldn't figure out a way to do it, as far as I can tell there is no way to add helper functionality to @JS()
library pixi.dynamic;
import 'package:js/js.dart';
@JS()
@anonymous
class DynamicSource {}
@JS()
@anonymous
class DynamicDescription
{
external get value;
external factory DynamicDescription({bool configurable, bool enumerable, bool writable, value });
}
// Interop to ES5+ functions that will allow us to get/set arbitrary properties on
// anonymous javascript objects.
@JS('Object.defineProperty')
external void defineProperty(object, String property, DynamicDescription description);
@JS('Object.getOwnPropertyDescriptor')
external DynamicDescription getOwnPropertyDescriptor(object, String property);
// A helper class for dealing with proxying anonymous JS objects that are to be
// used as maps and therefore do not have a fixed structure that can be defined
// ahead of time.
class Dynamic<T>
{
DynamicSource source;
Dynamic(this.source);
T operator [](String key)
{
return getOwnPropertyDescriptor(this.source, key)?.value;
}
operator []=(String key, T value)
{
defineProperty(this.source, key, new DynamicDescription(
value: value, writable: true, enumerable: true, configurable: true
));
return value;
}
} Given my initial example it would be used as follows @JS()
class Foo
{
external DynamicSource get items;
external set items(DynamicSource value);
external Foo();
}
void main()
{
// Retrieve an instance of Foo created somewhere in the external JS library
var foo = getFooFromSomewhere();
// Wrap the DynamicSource member so that it can be treated like a map
var items = new Dynamic<int>(foo.items);
print(items['mykey']);
items['mykey'] = 8;
} |
Sorry to re-open this issue, but I was playing around with the library again and found that the following works with the dartdevc (pub serve) but does not work when built (pub build). @JS()
library pixi.dynamic;
import 'package:js/js.dart';
import 'package:js/js_util.dart';
abstract class Dynamic<T>
{
T operator [](String key)
{
return getProperty(this, key) as T;
}
void operator []=(String key, T value)
{
setProperty(this, key, value);
}
}
@JS() @anonymous
class Resources extends Dynamic<Resource> {} When run via the dartdevc an object returned by an external JS library and treated as class |
Likely this should be an error with dartdevc too. |
This should be an error. The code size and performance implications for dart2js without strong mode are bad to the point where it should be prohibited. |
Ok, filed as a DDC bug. |
Thanks. It's a shame because it was a really neat way of tidying up my interop library. I guess I'll have to stick to using wrapper classes instead. |
Yes. Once Dart2JS takes full advantage of strong mode we should be able to make @js classes a lot more powerful without taking a performance hit. |
Excellent! I look forward to it |
|
I'm working on a package to interface with a javascript library that has a reasonably large API footprint. It's mostly going well and I've been able to implement dart equivalents of most of their examples, however there has been one problem that I've been unable to figure out:
There are a few places in the javascript library where they use anonymous objects as storage for arbitrary items. In effect they are using it like a
Map<String, dynamic>
but unfortunately I cannot seem to find a way to treat it as such via interop.I'm aware of, and have successfully used, the
@anonymous
attribute for sending structured anonymous objects to the js library but in this case I need to read a property that does not have a fixed structure. For example:where
items
is the object in question.I have also found
JsObject
in 'dart:js' but this does not appear to be usable in the context of 'package:js'. Perhaps allowing something like this would be helpful:Am I missing something, or is this a feature that would need to be added to 'package:js'?
The text was updated successfully, but these errors were encountered: