Electron ipcRenderer seems broken - electron

Original issue: https://github.com/electron/electron/issues/37067
I'm using Electron 12.0.6 and ipcRenderer seems broken sometime (both macOS and Windows):
The main process never received the message sent by ipcRenderer.send(), ipcRenderer.sendSync(), ipcRenderer.invoke(), ipcRenderer.postMessage()
Other renderer process never received the message sent by ipcRenderer.sendTo()
ipcRenderer.sendSync() always returns null
ipcRenderer.on() can still receive the message from other process
Unable to create a new <webview> element
ipcRenderer works fine in other webContents, including window and webview
ipcRenderer works normal after the page reloaded
I wonder how could I debug this issue? What information would help to debug this issue and how to collect such information?
Is there any guesses on this issue? For example, what causes ipcRenderer.sendSync() always returns null?
EDIT: After reading the source code of electron#12.0.6, it seems like chromium mojo message not sent?
// shell/renderer/api/electron_api_ipc_renderer.cc
v8::Local<v8::Value> SendSync(v8::Isolate* isolate,
gin_helper::ErrorThrower thrower,
bool internal,
const std::string& channel,
v8::Local<v8::Value> arguments) {
if (!electron_browser_remote_) {
thrower.ThrowError(kIPCMethodCalledAfterContextReleasedError);
return v8::Local<v8::Value>();
}
blink::CloneableMessage message;
if (!electron::SerializeV8Value(isolate, arguments, &message)) {
return v8::Local<v8::Value>();
}
blink::CloneableMessage result;
// >>> This line was called
electron_browser_remote_->MessageSync(internal, channel, std::move(message),
&result);
return electron::DeserializeV8Value(isolate, result);
}
v8::Global<v8::Context> weak_context_;
mojo::Remote<electron::mojom::ElectronBrowser> electron_browser_remote_;

Related

Distinct Stream in Dart

I'm writing a flutter app which sends commands via BlueTooth (FlutterBlue) to a device. The device controlls some LEDs.
The communication is working in general quite well but:
On the UI I have a slider controlling the light intensity. When I pull the slider there are more values generated than the bluetooth backend can handle.
In my first implementation I was sending the data directly to the bluetooth characteristic, resulting in exceptions from the bluetooth backend and some values get lost. It's hard to fade light down to zero.
In my second approach I'm using a stream and an await for loop to send the data. Now all values are send without any exceptions but it takes several seconds after releasing the slider until all values are send. Since I want direct visual feedback on the LEDs, this is not an option.
Since there are multiple commands of the same type to be send, I can skip all commands of the same type which were added while the bluetooth send routine was processing a write event.
I saw that there is a Stream.Distinct method but: It returns a new stream. So I have to exit my await for loop and handle the new stream.
Is there a way of removing undesired events from an existing stream without creating a new stream where I have to listen to?
Here is what I'm doing:
class MyBlueToothDevice {
BluetoothDevice _device;
List<BluetoothCharacteristic> _characteristics =
List<BluetoothCharacteristic>();
final _sendStream = StreamController<Tuple2<SendCommands, List<int>>>();
MyBlueToothDevice(this._device) {
_writeNext();
}
Future<void> write(SendCommands command, List<int> value) async {
if (isConnected) {
_sendStream.add(Tuple2<SendCommands, List<int>>(command, value));
// await _characteristics[command.index].write(value).catchError((value) {
// print("Characteristics.write error: $value");
// });
}
}
Future<void> _writeNext() async {
await for (var tuple in _sendStream.stream) {
await _characteristics[tuple.item1.index]
.write(tuple.item2)
.catchError((value) {
print("Characteristics.write error: $value");
});
}
}
}
The best solution is to use application state management to receive all the events from your slider. The state manager will then rate-limit the messages to the device to something it can handle, and also ensure that the most recent message is not lost.
A very basic solution would receive the slider value and update the value in the state manager. A periodic timer with a suitable rate could then update that value to the device; possibly only if the value actually changed since the last time it was sent.

error using Notification API on Dart

I've used Notifications working on a JavaScript app and It's very useful when you don't have to be all the time looking at the app when something important needs to be acknowledged. I tried to replicate some work on Dart but a reference error is shown on compiled to JS Chrome.
Do you know if It's going to be implemented for Chrome soon? or is It going to remain experimental?
Thanks in advance
This is the function which tries to call Notification API. Without Notification line, everything works, when I add Notification line I get this error "Uncaught ReferenceError: requestPermission is not defined" running the code as JavaScript. (I am importing 'dart:html')
void revisarInput() {
if ( valorLogin != '' ) {
indicador = true;
_ws.send( Util.formatearJsonSocket( 'loginPwd', { 'pwd': int.parse( valorLogin )}));
}
Notification.requestPermission();
}
This was a bug in dart2js, https://code.google.com/p/dart/issues/detail?id=22483 and is fixed for Dart 1.9.
This page says
https://developer.chrome.com/apps/notifications
Stable since Chrome 28

Call function in a dart polymer element [duplicate]

Having a weird issue. In my Dart code I have some polymer components on the screen and one of them has a method I call from my main().
I grab a reference to it by doing
PolyComp poly = querySelector("#idOfPolymer");
poly.flash();
This works perfectly in dart. The page loads up and PolyComp starts to flash. However when I run this in Chrome by running Build Polymer app from the Dart IDE, I get an error that says cannot call flash() on null.
I ended up making it flash by just using an event bus and letting PolyComp listen to my event, but this is overkill.
What am I doing wrong? This happens in the latest Chrome, Firefox and Safari.
Edit:
I built the following polymer app to JS also and ran into the same issue.
https://github.com/sethladd/dart-polymer-dart-examples/blob/master/web/todo_element/todo.html
Works on DartVM, not in Chrome because its calling a method on a null element.
When you run this code from the main() method it is probably a timing issue.
You can try something like
import "package:polymer/polymer.dart";
main() {
initPolymer().run(() {
// code here works most of the time
Polymer.onReady.then((e) {
// some things must wait until onReady callback is called
});
});
}
see also how to implement a main function in polymer apps

How to prevent onBeforeUnload listener in dart from prompting the user?

I basically want just to listen for 'onbeforeunload' to make sure the user won't receive 'connection lost' error messages from my ajax calls. i therefore registered an event and simply set a variable to true that i know to not bother the user with further error messages:
window.onBeforeUnload.listen((BeforeUnloadEvent e){
isUnloading = true;
});
in Dartium this works, after running dart2js i get a javascript alert with 'false':
according to related questions, to set the text I would have to set e.returnValue = 'Prompt'; - but what should i do if I do NOT want to show any dialog? - according to the MDN the prompt is shown for every non-void return value.. but how can i set returnValue to void? (null is not working) - is this a bug, or am i doing it wrong? (dart sdk 1.0.0.7)
There seems to be no way to prevent this dialog in Chrome if you subscribe to onBeforeUnload.
You can try the onPageHide event (works in Chrome, may not work in other browsers).

Dart Web Server: prevent crash

Id'like to develop a web services + web sockets server using dart but the problem is I can't ensure the server's high availability because of uncatched exceptions in isolates.
Of course, I have try-catched my main function, but this is not enough.
If an exception occurs in the then() part of a future, the server will crash.
Which means that ONE flawd request can put the server down.
I realize that this is an open issue but is there any way to acknoledge any crash WITHOUT crashing the VM so that the server can continue serving other requests ?
Thank you.
What I've done in the past is use the main isolate to launch a child isolate which hosts the actual web server. When you launch an isolate, you can pass in an "uncaught exception" handler to the child isolate (I also think you should be able to register one at the top-level as well, to prevent this particular issue, as referenced by the issue in the original question).
Example:
import 'dart:isolate';
void main() {
// Spawn a child isolate
spawnFunction(isolateMain, uncaughtExceptionHandler);
}
void isolateMain() {
// this is the "real" entry point of your app
// setup http servers and listen etc...
}
bool uncaughtExceptionHandler(ex) {
// TODO: add logging!
// respawn a new child isolate.
spawnFunction(isolateMain, uncaughtException);
return true; // we've handled the uncaught exception
}
Chris Buckett gave you a good way to restart your server when it fails. However, you still don't want your server to go down.
The try-catch only works for synchronous code.
doSomething() {
try {
someSynchronousFunc();
someAsyncFunc().then(() => print('foo'));
} catch (e) {
// ...
}
}
When your async method completes or fails, it happens "long" after the program is done with the doSomething method.
When you write asynchronous code, it's generally a good idea to start a method by returning a future:
Future doSomething() {
return new Future(() {
// your code here.
var a = b + 5; // throws and is caught.
return someAsyncCall(); // Errors are forwarded if you return the Future directly.
});
}
This ensures that if you have code that throws, it catches them and the caller can then catchError() them.
If you write this way, you have much less crashes, assuming that you have some error handling at the top level at least.
Whenever you are calling a method that returns a Future, either return it directly (like shown above) or catchError() for it so that you are handling the possible errors locally.
There's a great lengthy article on the homepage that you should read.

Resources