Skip to content
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

Various documentation fixes #4

Merged
merged 10 commits into from Jan 9, 2018
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
50 changes: 25 additions & 25 deletions lib/Valence.pm
Expand Up @@ -229,29 +229,29 @@ Valence - Perl interface to electron GUI tool-kit

=head1 DESCRIPTION

L<Electron|https://github.com/atom/electron> is chromium-based GUI application framework. It allows you to create "native" applications in HTML, CSS, and javascript. The L<Valence> perl module is an RPC binding that lets you use perl instead of javascript for the electron "main" process. It bundles a javascript module L<valence.js|https://github.com/hoytech/valence> which is responsible for proxying messages between the browser render process(es) and your perl controller process.
L<Electron|https://github.com/atom/electron> is a chromium-based GUI application framework. It allows you to create "native" applications in HTML, CSS, and JavaScript. The L<Valence> Perl module is an RPC binding that lets you use Perl instead of JavaScript for the electron "main" process. It bundles a JavaScript module L<valence.js|https://github.com/hoytech/valence> which is responsible for proxying messages between the browser render process(es) and your perl controller process.

Since valence is a generic RPC framework, none of the electron methods are hard-coded in the perl or javascript bridges. This means that all of the L<electron docs|https://github.com/atom/electron/tree/master/docs> are applicable and should be used as reference when developing with this module.
Since valence is a generic RPC framework, none of the electron methods are hard-coded in the Perl or JavaScript bridges. This means that all of the L<electron docs|https://github.com/atom/electron/tree/master/docs> are applicable and should be used as a reference when developing with this module.

B<NOTE>: This module depends on L<Alien::Electron> which will download and install the electron distribution appropriate for your operating system. On linux this depends on having the C<X11> environment variable set. See the L<Alien::Electron> documention for more details.
B<NOTE>: This module depends on L<Alien::Electron> which will download and install the electron distribution appropriate for your operating system. On Linux this depends on having the C<X11> environment variable set. See the L<Alien::Electron> documentation for more details.

=head1 DESIGN

=head2 ASYNC PROGRAMMING

Like browser programming itself, programming the perl side of a Valence application is done asynchronously. The L<Valence> package depends on L<AnyEvent> for this purpose so you can use whichever event loop you prefer. See the L<AnyEvent> documentation for details on asynchronous programming.
Like browser programming itself, programming the Perl side of a Valence application is done asynchronously. The L<Valence> package depends on L<AnyEvent> for this purpose so you can use whichever event loop you prefer. See the L<AnyEvent> documentation for details on asynchronous programming.

The C<run> method of the Valence context object simply waits on a condition variable that will never be signalled (well you can signal it if you want to, it's in C<< $valence->{cv} >>) in order to enter the event loop and "sleep forever". C<run> is mostly there so you don't need to type C<< use AnyEvent; AE::cv->recv >> in simple scripts/examples.

=head2 METHODS

The C<require> method initiates a C<require> call in the electron main process and immediately returns a C<Valence::Object>. Any methods that are called on this object will initiate the corresponding method calls in the electron main process and will also themselves return C<Valence::Object>s. The C<new> method is slightly special in that it will use the javascript C<new> function, but it too returns C<Valence::Object>s corresponding to the newly constructed javascript objects:
The C<require> method initiates a C<require> call in the electron main process and immediately returns a C<Valence::Object>. Any methods that are called on this object will initiate the corresponding method calls in the electron main process and will also themselves return C<Valence::Object>s. The C<new> method is slightly special in that it will use the JavaScript C<new> function, but it too returns C<Valence::Object>s corresponding to the newly constructed JavaScript objects:

my $main_window = $electron->attr('BrowserWindow')->new({ title => "My Title" });

C<Valence::Object>s are essentially perl-side references to values inside the electron main javascript process. If you destroy the last reference to one of these objects, their corresponding values will be deleted in the javascript process and eventually garbage collected.
C<Valence::Object>s are essentially Perl-side references to values inside the electron main JavaScript process. If you destroy the last reference to one of these objects, their corresponding values will be deleted in the JavaScript process and eventually garbage collected.

As well as calling methods on C<Valence::Object>s, you may also treat them as C<sub>s and pass in callbacks that receive the referenced values. This is how you can access javascript values from the perl process. For example:
As well as calling methods on C<Valence::Object>s, you may also treat them as C<sub>s and pass in callbacks that receive the referenced values. This is how you can access JavaScript values from the perl process. For example:

$main_window->getPosition->(sub {
my $pos = shift;
Expand All @@ -263,15 +263,15 @@ As well as calling methods on C<Valence::Object>s, you may also treat them as C<
C<Valence::Object> has a special C<attr> method which looks up an object attribute and returns a C<Valence::Object> referring to the attribute value. For example:

my $web_contents = $main_window->attr('webContents');
## similar to this JS: var web_contents = main_window.webContents;
## similar to this JavaScript var web_contents = main_window.webContents;

Eventually I may make attributes accessible via a hash reference overload which would be a slightly nicer syntax.

=head2 CALLBACKS

Because interacting with an electron process via valence is done asynchronously, callbacks are used nearly everywhere.

When a perl C<sub> is found in the arguments passed to a method, it is replaced with a stub that will be replaced with a javascript function inside the electron main process. When this javascript function is invoked, an asynchronous message will be sent to the perl process which will trigger the execution of your original C<sub>.
When a Perl C<sub> is found in the arguments passed to a method, it is replaced with a stub that will be replaced with a JavaScript function inside the electron main process. When this JavaScript function is invoked, an asynchronous message will be sent to the perl process which will trigger the execution of your original C<sub>.

For example, here is how to install a sub that will be executed whenever the main window comes into focus:

Expand All @@ -290,7 +290,7 @@ then it means that the C<electron> process has exited but you haven't handled th

=head1 DEBUGGING

If you set the C<VALENCE_DEBUG> value to C<1> or higher, you will see a prettified dump of the JSON protocol between the perl and electron process
If you set the C<VALENCE_DEBUG> value to C<1> or higher, you will see a prettified dump of the JSON protocol between the perl and electron processes

Sending to electron >>>>>>>>>>>>>>>>>
{
Expand Down Expand Up @@ -338,16 +338,16 @@ If you set C<VALENCE_DEBUG> to C<2> or higher, you will also see the standard er

=head1 IPC

An essential feature of valence is providing bi-directional, asynchronous messaging between your application and the browser render process. It does this over the standard input/standard output interface provided by C<valence.js>. Without this support we would need to allocate some kind of network port or unix socket and start something like an AJAX or websocket server.
An essential feature of valence is providing bi-directional, asynchronous messaging between your application and the browser render process. It does this over the standard input/standard output interface provided by C<valence.js>. Without this support we would need to allocate some kind of network port or Unix socket and start something like an AJAX or websocket server.

=head2 BROWSER TO PERL

In order for the browser to send a message to your perl code, it should execute something like the following javascript code:
In order for the browser to send a message to your Perl code, it should execute something like the following JavaScript code:

var ipcRenderer = require('electron').ipcRenderer;
ipcRenderer.send('my-event', 'my message');

On the perl side, you receive these messages like so:
On the Perl side, you receive these messages like so:

my $ipcMain = $electron->attr('ipcMain');
$ipcMain->on('my-event' => sub {
Expand All @@ -358,12 +358,12 @@ On the perl side, you receive these messages like so:

=head2 PERL TO BROWSER

Sending messages from perl to the browser should use code like this:
Sending messages from Perl to the browser should use code like this:

my $web_contents = $main_window->attr('webContents');
$web_contents->send('my-event' => 'my message');

And the javascript side can receive these messages like so:
And the JavaScript side can receive these messages like so:

var ipcRenderer = require('electron').ipcRenderer;
ipcRenderer.on('my-event', function(event, message) {
Expand All @@ -372,13 +372,13 @@ And the javascript side can receive these messages like so:

=head2 IPC READY EVENTS

Before applications can send messages from perl to javascript, the C<ipcRenderer.on()> function must have been called to handle these messages. If you try to send a message before this, it is likely that the message will be delivered to the browser before the handler has been installed so your message will be lost. Applications should have javascript send a message indicating that the communication channel is ready, after which the perl component can begin sending messages to the browser.
Before applications can send messages from Perl to JavaScript, the C<ipcRenderer.on()> function must have been called to handle these messages. If you try to send a message before this, it is likely that the message will be delivered to the browser before the handler has been installed, so your message will be lost. Applications should have JavaScript send a message indicating that the communication channel is ready, after which the Perl component can begin sending messages to the browser.

For an example of how this is done, see the C<t/ipc.t> test and how the perl side subscribes to a C<ready> IPC message before attempting to send its C<ping> message, and how the C<t/static/remote.html> arranges for javascript to send the C<ready> message after it has installed its C<ping> handler.
For an example of how this is done, see the C<t/ipc.t> test and how the Perl side subscribes to a C<ready> IPC message before attempting to send its C<ping> message, and how the C<t/static/remote.html> arranges for JavaScript to send the C<ready> message after it has installed its C<ping> handler.

=head1 TESTS

Currently this software has two tests, C<load.t> which verifies L<Valence> is installed and C<ipc.t> which starts electron and then proceeds to confirm bi-directional transfer of messages between javascript and perl.
Currently this software has two tests, C<load.t> which verifies L<Valence> is installed and C<ipc.t> which starts electron and then proceeds to confirm bi-directional transfer of messages between JavaScript and Perl.

=head1 BACKWARDS COMPATIBILITY

Expand All @@ -388,23 +388,23 @@ Presumably now that C<electron> has reached version C<1.0.0> it should now be mo

=head1 BUGS

A fairly large limitation with the proxying approach is that event handlers cannot prevent the default event from firing (ie with C<event.preventDefault()>). This is because the stub event handler in javascript simply forwards the event trigger and its arguments to the perl process and returns.
A fairly large limitation with the proxying approach is that event handlers cannot prevent the default event from firing (i.e. with C<event.preventDefault()>). This is because the stub event handler in JavaScript simply forwards the event trigger and its arguments to the perl process and returns.

As mentioned above, C<sub>s nested inside hashes or arrays will currently not properly get stubbed out (but this can be fixed if needed).

Attributes should ideally be accessed via a hash reference overload instead of the C<attr> special method.

C<new> methods cannot yet accept more than one parameter (due to a limitation in C<valence.js> -- how do you do this in JS?).
C<new> methods cannot yet accept more than one parameter (due to a limitation in C<valence.js> -- how do you do this in JavaScript?).

When a callback function is deleted on the javascript side, the perl-side doesn't know about this so its corresponding callback will remain forever. Is there a way to detect this in JS?
When a callback function is deleted on the JavaScript side, the Perl-side doesn't know about this so its corresponding callback will remain forever. Is there a way to detect this in JavaScript?

It currently always sends a C<save> (immediately followed by a C<destroy>) even when it doesn't need the value. This is inefficient and should be fixed using C<wantarray>.

Exceptions thrown in the JS side should be handled better (using L<Callback::Frame>).
Exceptions thrown in the JavaScript side should be handled better (using L<Callback::Frame>).

=head1 SEE ALSO

L<The Valence perl module github repo|https://github.com/hoytech/Valence-p5>
L<The Valence Perl module github repo|https://github.com/hoytech/Valence-p5>

L<Alien::Electron>

Expand All @@ -420,9 +420,9 @@ Doug Hoyte, C<< <doug@hcsw.org> >>

Copyright 2015-2016 Doug Hoyte.

This module is licensed under the same terms as perl itself.
This module is licensed under the same terms as Perl itself.

The bundled C<valence/valence.js> library is Copyright (c) 2015-2016 Doug Hoye and is licensed under the 2-clause BSD license.
The bundled C<valence/valence.js> library is Copyright (c) 2015-2016 Doug Hoyte and is licensed under the 2-clause BSD license.

Electron itself is Copyright (c) 2014-2016 GitHub Inc. and is licensed under the MIT license.

Expand Down