-
Notifications
You must be signed in to change notification settings - Fork 1.6k
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
How to use for loop with staticInterop? #48327
Comments
@sigmundch – can you direct? |
There are two angles on this question worth discussing: What to do about arrays? /cc @srujzs @rakudrama @rileyporter @jodinathan - I'm noticing that you are trying to use JSinterop to wrap javascript arrays, but I'd like to note that the default Our goal with static-interop is to make it possible to write most of the browser bindings outside the dart sdk (e.g. dart:html, svg, indexed-db, etc), but not necessarily to replace what we do with types exposed in our core libraries (like numbers or arrays). Unfortunately there are a few array-like APIs in the browser bindings too (e.g. What to do about other language features that are based on interfaces? @leafpetersen - curious on your take on this. So far we have used queries like "implements X" to enable certain features, and I wonder if we want to revisit this in the context of static-views/extension-types. This issue refers to the specific case of |
@sigmundch there are 11 classes that have the |
One idea that may be worth exploring is to use wrappers only at the time of iteration. Traditionally for JS-interop we don't want to wrap every object returned from JSinterop APIs because it becomes really expensive, however we could consider using a short-lived wrapper for the purpose of iteration. In this case, say if you were providing NodeList as an iterable, I could imagine the following: @JS()
@staticInterop
class NodeList { //* See note below why this is not generic
...
}
class NoteListIterable extends ListBase<Node> {
final NodeList list;
Node? operator[](int index) => list[key];
void operator[]=(int index, Node? value) => list[key] = value;
int get length => list.length;
set length(int value) => list.length = value;
}
...
method() {
var list = divElement.childNodes; // e.g. js_binding API to read childNodes
for (var child in NodeListIterable(list)) {
print(child);
}
} *PS: I noticed that your example above declares a generic |
We should be thinking in terms of supporting iterating JavaScript objects that support the JavaScript iterable protocol. If the wrapper is generic, I think we only need one, like this, but hopefully with a nicer name: for (var child in DartIterableViewOfJavaScriptIterable<Nodet>(list)) ... Perhaps we would like another for the array-like classes that we would like to index like These wrappers provide the Dart interface and Dart methods built on, but an array-like (with indexing via property accesses) cannot be easily passed back to JavaScript without unwrapping. Do we also want to support full iteration in the other direction, so that Dart |
But the generic part is important to inference, autocomplete etc. Instead of extending the |
Completely agree, it's just a hard tradeoff we have at the moment: if something is external and created outside the scope of Dart, then we can't assume it will be populated with Dart-specific information (like type arguments.) So far we treated internal Dart objects as controlled by our runtime (e.g. that's how regular Technically we could go with a middle ground: reify type arguments on external JavaScript objects that are fully created and controlled by the Dart application. Unfortunately it wouldn't be sound if we expect JavaScript code to be able to make updates to such objects, unless we introduce additional checks on the Dart side for every API that uses those type arguments. |
I think this is the best approach.
Maybe do some checks in DDC? |
maybe we could test the extension-types in this case @sigmundch ? |
This is tricky, because an unsound issue in one place can lead dart2js to generate invalid code from optimizations, making it very difficult to debug. |
Not sure I understand what you mean :), could you clarify? For context, that flag is in early stages and unfortunately not in a state we can use. The feature it represents is still being designed (it is also referred to as static views, here is a recent draft of the proposal). For what it's worth, our goal is to jump into it as soon as it is in a state that we can use :). In fact, the current work with |
I thought we could statically extend a type. In our case, we could statically add |
I've added a wrapper and now is possible to use Works until we have |
I see, currently NodeList myNodeList = ...;
myNodeList.forEach(print); // OK: forEach is found statically in the static-view
Iterable iterable = myNodeList;
iterable.forEach(print); // ERROR: forEach is not found virtually The second To really support virtual calls you'd need a real wrapper and not an erasable zero-cost wrapper like That said, I wonder if there is a a way to extend |
I thought with static views we could do something like: @JS('Array')
view JsArray<E> implements Iterable<E>, Iterator<E> {
Iterator<E> get iterator => this;
bool moveNext() => !next().done;
external E operator[](int index); // or use js_util
// other iterable methods that are external
}
@JS()
@staticOperator
class Document {}
typedef NodeList = JsArray<Node>;
extension AdvDocument on Document {
external NodeList get nodes;
} then the usage is just static: final nodes = document.nodes;
final canMoveNext = nodes.moveNext();
print(canMoveNext); which would compile to a complete static dynamic-like calls: const nodes = document.nodes;
const canMoveNext = !nodes.next().done;
print(canMoveNext); then we can use for (final node in document.nodes) {} (I guess the only problem there would be that the Dart and JS Iterable protocol are different but I also guess that we could adjust to it) however, this would not be possible: void foo(dynamic bar) {
if (bar is JsArray) {
// we can't know if bar is JsArray at runtime because it doesn't exist
}
} |
I am trying to use
staticInterop
to implement array interop in JS hereFrom what I understand, to be able to use
for
loops on instances theclass
need to implementIterable
with its members, however, usingstaticInterop
we can't have members.What can I do to be able to iterate the array with regular
for
loop?The text was updated successfully, but these errors were encountered: