dart-gde / chrome.dart

Provide Dart interop with chrome.* APIs for Chrome Packaged Apps
Other
125 stars 48 forks source link

Passing chrome.Entry to a Javascript function doesn't unwrap the DartObject #128

Open Pat-Laub opened 10 years ago

Pat-Laub commented 10 years ago

I'd expected a Dart chrome.Entry object to pass to JavaScript (as a function argument) with the equivalent Javascript type (chrome.fileSystem.Entry). Instead it appears as a DartObject. Passing the .jsProxy member sometimes seems to work but seems hacky/wrong.

For example: running this dart code

import 'package:chrome/chrome_app.dart' as chrome;
import 'package:js/js.dart' as js;

main() {
  var options = new chrome.ChooseEntryOptions(
      type: chrome.ChooseEntryType.OPEN_DIRECTORY);

  chrome.fileSystem.chooseEntry(options).then((result) {
    chrome.DirectoryEntry dirEntry = result.entry;
    js.context.saveHelloToDirectory(dirEntry);
  });
}

which passes a DirectoryEntry to this javascript

function saveHelloToDirectory(dirEntry) {
  console.log(dirEntry);

  dirEntry.getFile("hello_world.txt", {create: true, exclusive: false},

...

will give

Uncaught Error: NoSuchMethodError: Cannot call "getFile" on "#" (Object # has no method 'getFile')

If the dart line were changed to

js.context.saveHelloToDirectory(dirEntry.jsProxy);

then the code runs successfully but the compiler spits out

Warning: No member named 'jsProxy' in class 'DirectoryEntry'.

devoncarew commented 10 years ago

Passing the .jsProxy member sometimes seems to work but seems hacky/wrong.

It is hacky, but it's the state of the art for the chrome library right now. It's what we do under the covers in the generated code. The dart:js library doesn't automatically unpack objects when calling from dart --> JS - for example, calling something like a toJS() method. If I recall, the old package:js did have something like this.

For now, passing on the jsProxy is your best bet. You can do a (dirEntry as dynamic).jsProxy to avoid the compiler warning. We're looking at a better way to bind the DOM filesystem objects returned by the chrome APIs in order to avoid these corner cases showing up to users. No ETA though :(