php-embed
Version:
Bidirectional interoperability between PHP and Node.js in a single process
267 lines (263 loc) • 7.05 kB
JavaScript
var path = require('path');
var StringStream = require('../test-stream.js');
require('should');
function removeObjectIds(str) {
return str.replace(/object\(([^\)]*)\)#\d+/g, 'object($1)');
}
describe('Passing context object from JS to PHP', function() {
var php = require('../');
it('should pass all basic data types from JS to PHP', function() {
var out = new StringStream();
return php.request({
file: path.join(__dirname, 'context.php'),
stream: out,
context: {
a: false,
b: true,
c: -42,
d: (((1 << 30) - 1) * 4),
e: 1.5,
f: 'abcdef \uD83D\uDCA9',
g: { f: 1 },
h: function fname(x) { return x; },
i: new Buffer('abc', 'utf8'),
},
}).then(function(v) {
removeObjectIds(out.toString())
.replace(/int\(4294967292\)/,'float(4294967292)')
.should.equal([
'bool(false)',
'bool(true)',
'int(-42)',
'float(4294967292)',
'float(1.5)',
'string(11) "abcdef \uD83D\uDCA9"',
'int(1)',
'string(5) "fname"',
'int(42)',
'object(Js\\Buffer) (1) {',
' ["value"]=>',
' string(3) "abc"',
'}',
'',
].join('\n'));
});
});
it('should implement isset(), empty(), and property_exists', function() {
var out = new StringStream();
return php.request({
file: path.join(__dirname, 'context2.php'),
stream: out,
context: {
a: 0,
b: 42,
c: null,
d: undefined,
e: '0',
f: '1',
g: new Buffer('abc'),
},
}).then(function(v) {
removeObjectIds(out.toString()).should.equal([
'->a: int(0)',
'[\'a\']: int(0)',
'isset: bool(true)',
'empty: bool(true)',
'exists: bool(true)',
'',
'->b: int(42)',
'[\'b\']: int(42)',
'isset: bool(true)',
'empty: bool(false)',
'exists: bool(true)',
'',
'->c: NULL',
'[\'c\']: NULL',
'isset: bool(false)',
'empty: bool(true)',
'exists: bool(true)',
'',
'->d: NULL',
'[\'d\']: NULL',
'isset: bool(false)',
'empty: bool(true)',
'exists: bool(true)',
'',
'->e: string(1) "0"',
'[\'e\']: string(1) "0"',
'isset: bool(true)',
'empty: bool(true)',
'exists: bool(true)',
'',
'->f: string(1) "1"',
'[\'f\']: string(1) "1"',
'isset: bool(true)',
'empty: bool(false)',
'exists: bool(true)',
'',
'->g: object(Js\\Buffer) (1) {',
' ["value"]=>',
' string(3) "abc"',
'}',
'[\'g\']: object(Js\\Buffer) (1) {',
' ["value"]=>',
' string(3) "abc"',
'}',
'isset: bool(true)',
'empty: bool(false)',
'exists: bool(true)',
'',
'->h: NULL',
'[\'h\']: NULL',
'isset: bool(false)',
'empty: bool(true)',
'exists: bool(false)',
'',
'',
].join('\n'));
});
});
it('should handle exceptions in getters', function() {
var out = new StringStream();
var context = {};
Object.defineProperty(context, 'a', { get: function() {
throw new Error('boo');
}, });
return php.request({
source: [
'call_user_func(function () {',
' try {',
" var_dump($_SERVER['CONTEXT']->a);",
' } catch (Exception $e) {',
" echo 'exception caught';",
' }',
'})',
].join('\n'),
stream: out,
context: context,
}).then(function() {
out.toString().should.equal('exception caught');
});
});
it('should implement __set and __unset', function() {
var out = new StringStream();
var context = { a: 42 };
Object.defineProperty(context, 'b', {
get: function() { return 13; },
set: function(v) { this.a = v; },
});
return php.request({
source: [
'call_user_func(function () {',
" $c = $_SERVER['CONTEXT'];",
" echo 'a is '; var_dump($c->a);",
" echo 'b is '; var_dump($c->b);",
' $c->a = 1;',
" echo 'a is '; var_dump($c->a);",
" echo 'b is '; var_dump($c->b);",
' $c->b = 2;',
" echo 'a is '; var_dump($c->a);",
" echo 'b is '; var_dump($c->b);",
" $c['b'] = 3;",
" echo 'a is '; var_dump($c->a);",
" echo 'b is '; var_dump($c->b);",
' unset($c->a);',
" echo 'a is '; var_dump($c->a);",
" echo 'exists? '; var_dump(property_exists($c, 'a'));",
' try {',
' unset($c->b);',
' } catch (Exception $e) {',
" echo 'exception caught';",
' }',
'})',
].join('\n'),
stream: out,
context: context,
}).then(function() {
out.toString().should.equal([
'a is int(42)',
'b is int(13)',
'a is int(1)',
'b is int(13)',
'a is int(2)',
'b is int(13)',
'a is int(3)',
'b is int(13)',
'a is NULL',
'exists? bool(false)',
'exception caught',
].join('\n'));
});
});
it('should handle exceptions in setters', function() {
var out = new StringStream();
var context = {};
Object.defineProperty(context, 'a', { set: function() {
throw new Error('boo');
}, });
return php.request({
source: [
'call_user_func(function () {',
' try {',
" $_SERVER['CONTEXT']->a = 42;",
' } catch (Exception $e) {',
" echo 'exception caught';",
' }',
'})',
].join('\n'),
stream: out,
context: context,
}).then(function() {
out.toString().should.equal('exception caught');
});
});
it('should allow constructing buffers from PHP', function() {
var out = new StringStream();
var context = { b: new Buffer('abc') };
return php.request({
source: [
'call_user_func(function () {',
" $b = $_SERVER['CONTEXT']->b;",
" $bb = new $b('defgh');",
' var_dump($bb);',
'})',
].join('\n'),
stream: out,
context: context,
}).then(function() {
removeObjectIds(out.toString()).should.equal([
'object(Js\\Buffer) (1) {',
' ["value"]=>',
' string(5) "defgh"',
'}',
'',
].join('\n'));
});
});
it('should implement __toString', function() {
var out = new StringStream();
var A = function A(v) { this.f = v; };
A.prototype.toString = function() { return JSON.stringify(this.f); };
var context = { a: new A(32), b: {} };
return php.request({
source: [
'call_user_func(function () {',
" $c = $_SERVER['CONTEXT'];",
" echo 'a is ' . $c->a . '\n';",
" echo 'b is ' . $c->b . '\n';",
" $c->a->f = 'abc';",
" echo 'a is ' . $c->a . '\n';",
'})',
].join('\n'),
stream: out,
context: context,
}).then(function() {
out.toString().should.equal([
'a is 32',
'b is [object Object]',
'a is "abc"',
'',
].join('\n'));
});
});
});