Skip to content

Dart2JS ignores @JSName annotations when a type is used for external field #33527

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

Open
lexaknyazev opened this issue Jun 20, 2018 · 3 comments
Open
Labels
area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop. web-dart2js

Comments

@lexaknyazev
Copy link
Contributor

Dart SDK 2.0.0-dev.63.0

Dart2JS doesn't generate a proper getter for ByteBuffer.lengthInBytes when used with package:js.

JS code

var buffer = new ArrayBuffer(1024);

main.dart

@JS()
library js_interop;

import 'dart:typed_data';
import 'package:js/js.dart';

@JS()
external ByteBuffer get buffer;

void main() {
  print(buffer.lengthInBytes);
}

Output:

    main: function() {
      // TypeError: self.buffer.get$lengthInBytes is not a function
      H.printString(H.S(self.buffer.get$lengthInBytes()));
    }

DDC works fine.

@lexaknyazev
Copy link
Contributor Author

The issue isn't specific to that field. Looks like Dart2JS ignores @JSName annotations when a type is used for external field.

new ByteData.view(buffer);

compiles to

    ByteData_ByteData$view: function(buffer, offsetInBytes, $length) {
      // TypeError: buffer.asByteData$2 is not a function
      return buffer.asByteData$2(offsetInBytes, $length);
    }

@lexaknyazev lexaknyazev changed the title Dart2JS doesn't generate a getter for ByteBuffer.lengthInBytes when used with package:js Dart2JS ignores @JSName annotations when a type is used for external field Jun 21, 2018
@vsmenon vsmenon added the area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop. label Jul 20, 2019
@lexaknyazev
Copy link
Contributor Author

Seems like Dart2JS cannot reliably map JS ArrayBuffer to Dart ByteBuffer at all. A workaround involves creating a view on the JS side, passing it to Dart, and getting the ByteBuffer from there.

Assuming that JS global scope contains myBuffer created as:

var buffer = new ArrayBuffer(1024);

Dart's workaround looks like:

import 'dart:typed_data';
import 'package:js/js.dart';
import 'package:js/js_util.dart';

@JS('Uint8Array')
external Object get JSUint8Array;

@JS('buffer')
external Object get _buffer;

ByteBuffer get buffer =>
    (callConstructor(JSUint8Array, [_buffer]) as Uint8List).buffer;

Confirmed again on 2.13.0-211.6.beta.

@sigmundch
Copy link
Member

@lexaknyazev - thanks for your great small reproduction examples and for bringing this back to our attention!

It appears to me that this is a tree-shaking issue triggered from mixing JS-interop and native types. Dart2js has a special representation of native types exposed from the browser. These are the types we have in dart:typed_data and dart:html etc. Dart2js treats these native types as being separate from JS-interop types and as a result, it doesn't realize that ByteBuffer get buffer is a way in which ByteBuffer is live.

Going back to your original program on the top. It appears that changing it to explicitly use the ByteBuffer from Dart to ensure that the compiler recognizes the type to be in-use, is enough to make the JS-interop API start working.

For example, try this:

@JS()
library js_interop;

import 'dart:typed_data';
import 'package:js/js.dart';

@JS()
external ByteBuffer get buffer;

void main() {
  print(new Uint8List(0).buffer.lengthInBytes); // added only to make ByteBuffer marked as live
  print(buffer.lengthInBytes);
}

@srujzs @rakudrama - This is similar to that in #45745 (comment)

I think it may be worth studying the cost of marking all native types live in light of our plans to migrate a bulk of dart:html APIs to a static JS-interop implementation.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area-web-js Issues related to JavaScript support for Dart Web, including DDC, dart2js, and JS interop. web-dart2js
Projects
None yet
Development

No branches or pull requests

4 participants