Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
[js] Implemente simple conversion/wrapping of some basic things betwe…
…en NQP/native js.
  • Loading branch information
pmurias committed Feb 13, 2016
1 parent b31afba commit b9ab65b
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 21 deletions.
36 changes: 17 additions & 19 deletions examples/webpacked/example.nqp
@@ -1,31 +1,29 @@
sub js($code) {
nqp::getcomp("JavaScript").eval($code);
}
js('window.wrap = function(func) {return {"$call": func}}');
js('window.unwrap = function(code_ref) {return function() {code_ref.$call(null, {})}}');

my &set-draw := js('wrap(function($CTX, $NAMED, cb) {window.draw = unwrap(cb)})');
my &set-setup := js('wrap(function($CTX, $NAMED, cb) {window.setup = unwrap(cb)})');
my &fill := js('wrap(function($CTX, $NAMED, color) {fill(color.value)})');
my &ellipse := js('wrap(function($CTX, $NAMED, a, b, c, d) {ellipse(a, b, c.value, d.value)})');
my &createCanvas := js('wrap(function($CTX, $NAMED, width, height) {createCanvas(width.value, height.value)})');
my &mouseX := js('wrap(function($CTX, $NAMED) {return mouseX})');
my &mouseY := js('wrap(function($CTX, $NAMED) {return mouseY})');
my &mouseIsPressed := js('wrap(function($CTX, $NAMED) {return mouseIsPressed ? 1 : 0})');
my &set-draw := js('(function(cb) {window.draw = cb})');
my &set-setup := js('(function(cb) {window.setup = cb})');
my &mouseX := js('(function() {return mouseX})');
my &mouseY := js('(function() {return mouseY})');
my &mouseIsPressed := js('(function() {return mouseIsPressed ? 1 : 0})');

sub setup() {
my &fill := js('fill');
my &ellipse := js('ellipse');
my &createCanvas := js('createCanvas');

createCanvas(640, 480);
}
sub draw() {
if mouseIsPressed() {
fill(0);
} else {
fill(255);
}
ellipse(mouseX(), mouseY(), 80, 80);
set-draw(-> {
if mouseIsPressed() {
fill(0);
} else {
fill(255);
}
ellipse(mouseX(), mouseY(), 80, 80);
});
}

set-setup(&setup);
set-draw(&draw);

nqp::say("Hello Fancy Browser World");
42 changes: 41 additions & 1 deletion src/vm/js/nqp-runtime/core.js
Expand Up @@ -532,9 +532,49 @@ op.bindcomp = function(language, compiler) {
return (compilerRegistry[language] = compiler);
};

function WrappedFunction(func) {
this.func = func;
}

WrappedFunction.prototype.$apply = function(args) {
var converted = [];
for (var i = 2; i < args.length; i++) {
converted.push(toJS(args[i]));
}
return fromJS(this.func.apply(null, converted));
}

WrappedFunction.prototype.$call = function(args) {
return this.$apply(arguments);
}

function fromJS(obj) {
if (typeof obj === 'function') {
return new WrappedFunction(obj);
} else {
return obj;
}
}

function toJS(obj) {
if (obj instanceof NQPInt) {
return obj.value;
} else if (obj instanceof CodeRef) {
return function() {
var converted = [null, {}];
for (var i = 0; i < arguments.length; i++) {
converted.push(fromJS(arguments[i]));
}
return toJS(obj.$apply(converted));
};
} else {
return obj;
}
}

compilerRegistry['JavaScript'] = {
eval: function(ctx, named, code) {
return eval(code);
return fromJS(eval(code));
}
};

Expand Down
10 changes: 9 additions & 1 deletion t/js/getcomp-js.t
@@ -1,4 +1,12 @@
plan(1);
plan(3);
my $comp := nqp::getcomp('JavaScript');
my $helloworld := $comp.eval('"Hello " + "World"');
ok($helloworld eq 'Hello World',"getting a simple string from JavaScript");

my $square := $comp.eval('(function(num) {return num*num})');
ok($square(4) == 16, "passing integers to a js func");

my $twice := $comp.eval('(function(func) {return function(x) {return func(func(x))}})');
my $twiced := $twice(sub ($x) {"[$x]"})("abc");
ok($twiced eq '[[abc]]', 'passing an calling a NQP function on the JavaScript side');

0 comments on commit b9ab65b

Please sign in to comment.