Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

cleaned up inline documentation

  • Loading branch information...
commit ceee387cc3e30f656ba2a24cc975b8d29595fc18 1 parent 4fd12f4
@olalonde authored
Showing with 91 additions and 72 deletions.
  1. +2 −0  .gitignore
  2. +4 −3 js/demo.js
  3. +85 −69 src/node_gtknotify.cpp
View
2  .gitignore
@@ -0,0 +1,2 @@
+*~
+.lock-wscript
View
7 js/demo.js
@@ -1,7 +1,8 @@
var notify = require("../build/default/gtknotify.node"); // node.js stuff
-var notification = new notify.Notification();
+var notification = new notify.notification();
+console.log(notification.send("yippi"));
//notification.icon = "terminal";
//notification.title = "Notification title";
-notification.text = "Some text here...";
-console.log(notification.send("yippi"));
+//notification.text = "Some text here...";
+//console.log(notification.send("yippi"));
View
154 src/node_gtknotify.cpp
@@ -1,111 +1,127 @@
+//
+// This class is a native C++ Node.js extension for creating GTK+ desktop notification
+//
#include <v8.h>
#include <node.h>
// We need those two libraries for the GTK+ notification
#include <gtkmm.h>
#include <libnotifymm.h>
-// V8 documentation:
-// Context: a context is an execution environment that allows separate, unrelated, JavaScript applications to run in a single instance of V8.
-// must be explicitly specified
-// Handles: Local (deleted when scope deleted),
-// Persistent (deleted manually),
-// Handle (parent class)
-// Handle scope: a container that holds lots of handles.
-// when handle scope's destructor is called (implicitly called when ~ called) all handles created within that scope are removed
-// Template: A template is a blueprint for JavaScript functions and objects in a context (i.e. Google Chrome's DOM)
-// Function template: A function template is the blueprint for a single function.
-// Object templates: Each function template has an associated object template. accessors/interceptor C++ callbacks
-
-// todo: remove "using namespace" for less confusion node vs v8
-using namespace node;
+/*
+
+= V8 recap =
+
+More detailed info at http://code.google.com/apis/v8/embed.html
+
+== Context ==
+
+A context is an execution environment that allows separate, unrelated, JavaScript applications to run in a single instance of V8.
+Must be explicitly declared.
+
+== Handles ==
+
+Defines the lifetime of an object.
+
+Local (deleted when scope deleted),
+Persistent (deleted manually),
+Handle (parent class)
+
+== Handle scope ==
+
+A container that holds lots of handles.
+When handle scope's destructor is called (implicitly called when ~ called) all handles created within that scope are removed
+
+== Templates ==
+
+A template is a blueprint for JavaScript functions and objects in a context. You can use a template to wrap C++ functions and data structures within JavaScript objects so that they can be manipulated by JavaScript scripts. (i.e. a browser's DOM aka 'document')
+
+Function template: A function template is the blueprint for a single function.
+Object templates: Each function template has an associated object template. accessors/interceptor C++ callbacks
+
+*/
+
+//using namespace node;
using namespace v8;
class Gtknotify : node::ObjectWrap {
private:
public:
- // Function template for notification()
- static v8::Persistent<FunctionTemplate> persistent_function_template;
+ Gtknotify() {}
+ ~Gtknotify() {}
- // Node: the target is the "module", it's where your extension will be loaded into
+ // Holds our constructor function
+ static v8::Persistent<FunctionTemplate> persistent_function_template;
+
+ // @Node.js calls Init() when you load the extension through require()
+ // Init() defines our constructor function and prototype methods
+ // It then binds our constructor function as a property of the target object
+ // Target is the "target" onto which an extension is loaded. For example:
+ // var notify = require("../build/default/gtknotify.node"); will bind our constructor function to notify.Notification
+ // so that we can call "new notify.Notification();"
static void Init(Handle<Object> target) {
- /* V8 PART */
- // This scope will contain all local handles within this method (in other words, it will contain local_function_template)
+ // We need to declare a V8 scope so that our local handles are eligible for garbage collection.
+ // once the Init() returns.
v8::HandleScope scope;
-
- // Map our function template to the C++ New() method
- // Need to create local template first because that's what v8::FunctionTemplate::New returns
-
- // irc convo
- // <oli> anyone knows why you need to make a local function template before making it persistent?
- // Local<FunctionTemplate> t = FunctionTemplate::New(New); s_ct = Persistent<FunctionTemplate>::New(t);
- // <bradleymeck> oli mainly just readability, you *could* cast it as you assign to t
- // <oli> I assume v8::FunctionTemplate::New returns a local handle
- // <bradleymeck> it does, when im talking about casting here im talking about the v8 api cast not c cast
+ // Wrap our New() method so that it's accessible from Javascript
v8::Local<FunctionTemplate> local_function_template = v8::FunctionTemplate::New(New);
- // Make our local function template persistent
- persistent_function_template = v8::Persistent<FunctionTemplate>::New(local_function_template);
- /* V8 doc:
- Each JavaScript point object keeps a reference to the C++ object for which it is a wrapper with an internal field.
- These fields are so named because they cannot be accessed from within JavaScript, they can only be accessed from C++ code.
- An object can have any number of internal fields, the number of internal fields is set on the object template as follows: */
- persistent_function_template->InstanceTemplate()->SetInternalFieldCount(1);
- // Map our function template to a Javascript function name, so it can be called from Javascript: Notification()
- persistent_function_template->SetClassName(v8::String::NewSymbol("Notification"));
-
- /* NODE PART */
- // Arguments: function template, JS method name, C++ method
- // @see https://github.com/joyent/node/blob/v0.2.0/src/node.h#L34
- NODE_SET_PROTOTYPE_METHOD(persistent_function_template, "send", Send);
- // Add .notification() to the target, "module" so we expose our function as module.notification();
- target->Set(String::NewSymbol("Notification"), persistent_function_template->GetFunction());
+ // Make it persistent and assign it to our object's persistent_function_template attribute
+ Gtknotify::persistent_function_template = v8::Persistent<FunctionTemplate>::New(local_function_template);
+ // Each JavaScript object keeps a reference to the C++ object for which it is a wrapper with an internal field.
+ Gtknotify::persistent_function_template->InstanceTemplate()->SetInternalFieldCount(1); // 1 since this is a constructor function
+ // Set a class name for objects created with our constructor
+ Gtknotify::persistent_function_template->SetClassName(v8::String::NewSymbol("Notification"));
+
+ // @Node.js macro to help bind C++ methods to Javascript methods (see https://github.com/joyent/node/blob/v0.2.0/src/node.h#L34)
+ // Arguments: our constructor function, Javascript method na,e, C++ method name
+ NODE_SET_PROTOTYPE_METHOD(Gtknotify::persistent_function_template, "send", Send);
+
+ // Set the "notification" property to the target and assign it to our constructor function
+ target->Set(String::NewSymbol("notification"), Gtknotify::persistent_function_template->GetFunction());
}
- Gtknotify() {}
-
- ~Gtknotify() {}
-
- // Called when our class is created (constructor function)
- // Instantiates C++ object
+ // new Notification();
+ // This is our constructor function. It instantiate a C++ Gtknotify object and returns a Javascript handle to this object.
static Handle<Value> New(const Arguments& args) {
HandleScope scope;
Gtknotify* gtknotify_instance = new Gtknotify();
- // stores a reference to the C++ Gtknotify object inside the args.This() value
- gtknotify_instance->Wrap(args.This()); // Inherited from node::ObjectWrap
+ // Wrap our C++ object as a Javascript object
+ gtknotify_instance->Wrap(args.This());
- // Once it is wrapped up, it returns args.This(), which is just like what the new operator does in Javascript,
- // returning the this as an object.
+ // Our constructor function returns a Javascript object which is a wrapper for our C++ object,
+ // This is the expected behavior when calling a constructor function with the new operator in Javascript.
return args.This();
}
-
+
+ // notification.send();
+ // This is a method part of the constructor function's prototype
static v8::Handle<Value> Send(const Arguments& args) {
v8::HandleScope scope;
- // Extract C++ object reference from JS object passed as args.This()
+ // Extract C++ object reference from "this" aka args.This() argument
Gtknotify* gtknotify_instance = node::ObjectWrap::Unwrap<Gtknotify>(args.This());
- // todo: notify_instance->send();
- //Local<String> result = String::New("Hello World");
- // LIBNOTIFY
- v8::String::Utf8Value str(args[0]); // Convert first argument to V8 String
+ // Convert first argument to V8 String
+ v8::String::Utf8Value v8str(args[0]);
+ // see http://library.gnome.org/devel/libnotify/0.7/NotifyNotification.html
Notify::init("Basic");
- // Arguments: title, content, icon
- Notify::Notification n("Alert", *str, "terminal"); // *str = c string
+ // Args: title, content, icon
+ Notify::Notification n("Alert", *v8str, "terminal"); // *v8str points to the C string
// Display notification
n.show();
-
+ // Return value
return v8::Boolean::New(true);
}
};
-// Why this?
-v8::Persistent<FunctionTemplate> Gtknotify::persistent_function_template;
-
+// What follows is boilerplate code:
+
/* Thats it for actual interfacing with v8, finally we need to let Node.js know how to dynamically load our code.
Because a Node.js extension can be loaded at runtime from a shared object, we need a symbol that the dlsym function can find,
so we do the following: */
-// @see http://www.freebsd.org/cgi/man.cgi?query=dlsym
-// cause of name mangling in C++, we use extern C here
+// See http://www.freebsd.org/cgi/man.cgi?query=dlsym
+// Cause of name mangling in C++, we use extern C here
+v8::Persistent<FunctionTemplate> Gtknotify::persistent_function_template;
extern "C" {
static void init(Handle<Object> target) {
Gtknotify::Init(target);
Please sign in to comment.
Something went wrong with that request. Please try again.