by Fedor Indutny / @indutny
io.js TC member and...
(node.js core team member)
function Point(x, y, z) {
this.x = x;
this.y = y;
this.z = z;
}
This is JS ^
class Point {
public:
double x;
double y;
double z;
};
This is C++ ^
function add(x, y) {
return x + y;
}
add(0, 1); // <- good
add('foo', 'bar'); // <- polymorphism!
function Parser() {
}
Parser.freelist = [];
Parser.get = function() {
if (this.freelist.length)
return this.freelist.pop();
return new Parser();
};
Parser.prototype.release = ...;
Node.js C++ layer:
Lives on top of the event-loop
Provides
Start with history of the subject
to ease the understanding of
C++ layer
Node.js uses git since beginning
The history is in
git log & git blame
`git log deps/v8` - v8 fighting us
`git log src/` - us fighting v8
“add readme and initial code”
Two C/C++ dependencies except V8:
./server script.js
function Process(request) {
if (options.verbose) {
log("Processing " + request.host +
request.path +
" from " + request.referrer +
"@" + request.userAgent);
}
if (!output[request.host])
output[request.host] = 1;
else
output[request.host]++
}
(Just a Proof-of-Concept)
(Mapping uri, headers, method to JS object)
Quickly jumping to
064c8f02 commit
“Use ObjectWrap base class for File, Socket, Server.”
One API to wrap all objects
class File : public ObjectWrap {
public:
File(Handle<Object> handle)
: ObjectWrap(handle) {
}
};
are ObjectWrap instances
HTTP server still provided by liboi, node.js is using libev
grown
matured (a bit)
Separating JS from C++
CommonJS
tons of core modules
ObjectWrap is a public API now
(polished out for and by community)
Previously all C++ classes were
global objects
In v0.2 they are provided by process.binding()
> process.binding('fs');
{ access: [Function: access],
close: [Function: close],
open: [Function: open],
...lots of stuff...
...and similar stuff for other modules too
Lots of new stuff!
(We are interested only in C++)
Outgrown ObjectWrap
(src/node_object_wrap.h)
Now using AsyncWrap
(src/async-wrap.h)
(two fields: parent and providerType)
require('fs')
Just loads lib/fs.js and executes it.
JS is not capable of FS operations.
No networking either.
But... I need:
fs.writeFileSync()
http.request()
Lots of low-level C++ stuff outside of the JS-land
Let's learn by example
Though, require('fs') is boring
let's move to
require('net')
All powered by C++ machinery!
Provided by bindings:
process.binding()Bindings provide JS classes:
Purpose of these classes:
`net.connect()` workflow:
C++ classes are either:
How does process.binding() work?
NODE_MODULE_CONTEXT_AWARE_BUILTIN(
fs,
node::InitFs)
Has kind of same effect as:
cppModules['fs'] = {
initialized: false,
initFn: InitFS
};
So what process.binding() does?
process.binding = function(moduleName) {
var module = cppModules[moduleName];
if (module.initialized)
return module.exports;
module.exports = {};
module.initFn(module.exports);
return module.exports;
};
What initFn does?
Initializes module, like in CommonJS
Thanks, captain!
Exports functions and classes
Each exported JS class has
C++ counterpart
Most of them inherit from AsyncWrap
Small reminder. Two kinds of classes:
Handle and Wrap
Garbage Collector destroys only:
Handles
Requests are manually destroyed
after async action completion
(i.o.w. after callback)
You debug io.js issue, and find out that it
is crashing on:
var FooBar = process.binding('foo_bar').FooBar;
// Crashes here:
var f = new FooBar();
Where will you search for FooBar?
Somewhere in src/, searching by:
NODE_MODULE_CONTEXT_AWARE_BUILTIN(foo_bar, ..)
This will be most likely in src/foo_bar.cc
Renovation through making stuff public
We did it for ObjectWrap
We should do it for StreamWrap
StreamWrap wasn't that bad in v0.10
Was modified a lot for v0.12
Because we needed TLS streams in C++
Looks terrible in v0.12
But JS streams works so well...
They support multi-level piping
and are transparent to the user!
What if...
StreamBase in io.js
To the Rescue!
StreamBase (previosuly StreamWrap)
Still needs to be done:
Because: