dart-lang / sdk

The Dart SDK, including the VM, JS and Wasm compilers, analysis, core libraries, and more.
https://dart.dev
BSD 3-Clause "New" or "Revised" License
10.21k stars 1.57k forks source link

JS Interop: toString() isn't calling JS's toString() #30096

Open nex3 opened 7 years ago

nex3 commented 7 years ago

When I compile the following code with dart2js:

import 'package:js/js.dart';

@JS('Buffer.from')
external Buffer bufferFrom(String source, String encoding);

@JS()
class Buffer {
  external String toString();
}

void main() {
  print(bufferFrom("foobar", "utf8").toString());
}

and run it on Node (using this preamble), it prints [102, 111, 111, 98, 97, 114]. However, if I run node directly and write Buffer.from("foobar", "utf8").toString(), I get "foobar" as expected.

cedx commented 6 years ago

I've also encountered a variant of this issue:

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

@JS()
class Buffer {
  external static Buffer from(value);
  external String toString([String encoding]);
}

void main() {
  var buffer = Buffer.from([102, 111, 111, 66, 97, 114]);

  print(buffer.runtimeType);
  // Uint8List

  expect(buffer.toString('utf8'), equals('fooBar'));
  // NoSuchMethodError: method not found: 'toString$1' (t1.toString$1 is not a function)
}

The Buffer class is casted to a Uint8List, probably because on recent Node.js versions, Buffer extends from Uint8Array.

So we can't use toString(encoding) as this signature is not supported by the Uint8List class.

ailabs-software commented 4 years ago

In case it helps anyone else still learning Dart interop and trying to work around this issue: You can treat buffer as List<int> type, which can be decoded to string via utf8.encode() (from dart:convert).

At least, this was enough to get Node libsass bindings working via package:js for me (Dart sass didn't work out for me in "dart2js" last I tried).