dart-gde / chrome.dart

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

Port.postMessage is a JsFunction, which is surprising #163

Closed jiridanek closed 9 years ago

jiridanek commented 10 years ago

Having created a connection

chrome.Port connection = chrome.runtime.connect(chrome.runtime.id, null);

one may wish to postMessage to it

connection.postMessage({'joke': "Knock knock"});

But doing this obvious thing results in an exception being thrown

Unhandled exception:
Class 'JsFunction' has no instance method 'call'.

NoSuchMethodError: method not found: 'call'
Receiver: Instance of 'JsFunction'
Arguments: [Instance of '_LinkedHashMap']
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:45)

This is the result of the following line in Port class in runtime.dart

dynamic get postMessage => jsProxy['postMessage'];

So I have to call it in this silly way

js.JsFunction postMessage = connection.postMessage;
postMessage.apply([{'joke': "Knock knock"}], thisArg: connection.jsProxy);

or possibly

connection.jsProxy.callMethod(...);

This makes no sense, IMO.

zoechi commented 10 years ago

see also #135

I was able to send a message this way: p.jsProxy.callMethod('postMessage', [new JsObject.jsify({'response': 'init', 'tabId': 'none'})]); I was not able to receive a message. I can register a onMessage callback but when I actually receive a message I get an error output on the console but my callback is not called.

eukreign commented 9 years ago

The solution to this is to update the generated Port code with the code below replacing all previous instances of onMessage and postMessage:

  ChromeStreamController<OnMessageEvent> _onMessage;
  Stream<OnMessageEvent> get onMessage {
    if (_onMessage == null) {
      _onMessage = new ChromeStreamController<OnMessageEvent>.threeArgs(()=>jsProxy, 'onMessage', _createOnMessageEvent);
    }
    return _onMessage.stream;
  }

  void postMessage(dynamic message) =>
      jsProxy.callMethod('postMessage', [jsify(message)]);

Once you do that then this works:

  chrome.Port port = chrome.runtime.connect('', new chrome.RuntimeConnectParams()..name='panel');
  port.postMessage({'name': 'init', 'tabId': chrome.devtools.inspectedWindow.tabId});
  port.onMessage.listen((msg) => print(msg));

As soon as the generator is working again (see: #205) I can look into integrating this fix properly.

gyulavoros commented 9 years ago

Should this fix #150 too?

eukreign commented 9 years ago

@gyulavoros, see my pull request #207 for fix to #150.

gyulavoros commented 9 years ago

@eukreign thank you sir!