JE

 view release on metacpan or  search on metacpan

t/bind_class.t  view on Meta::CPAN

);

$j->bind_class(
	package => 'NumberOnly',
	constructor => sub { bless [], 'NumberOnly' },
	to_string => undef,
	to_number => sub { 12345 }
);

$j->bind_class(
	package => 'StringOnly',
	constructor => sub { bless [], 'StringOnly' },
	to_string => sub { 'Here you are' },
	to_number => undef
);

$j->bind_class(
	package => 'HintRequired',
	constructor => sub { bless [], 'HintRequired' },
	to_primitive => undef,
	to_string => sub { 'string' },
	to_number => sub { 'number' },
);

$j->bind_class(
	package => 'NotPrimitive',
	constructor => sub { bless [], 'NotPrimitive' },
	to_primitive => undef
);
$j->{diag} = \&diag unless $j->{diag};

defined $j->eval(<<'})() ') or die;

(function(){
	var t1 = new Heffelump
	var t2 = new Oliphaunt
	var t3 = new Elephant
	var t4 = new Gorilla
	var t5 = new NumberOnly
	var t6 = new StringOnly
	var t7 = new HintRequired
	var t8 = new NotPrimitive
	var error;

	is(String(t1), 'Look, we have a Heffelump')	
	is(   + t1, 678)
	is(String(t2), 'Look, we have an Oliphaunt')	
	is(   + t2, 678)
	is(String(t3), 'Look, we have an Elephant')	
	is(   + t3, 678)
	is('' + t4, 'no hint')	
	is(   + t4, 98765)
	is(String(t4), 'string')
	is(+t5, 12345)
	error=false;try{String(t5)}catch(e){error = true}ok(error)
	is(String(t6), 'Here you are')
	error=false;try{+ t6}catch(e){error = true}ok(error)
	is(String(t7), 'string')
//diag(t7)
//diag(+ (t7))
	is(     + t7 , NaN)
	error=false;try{'' + t7}catch(e){error = true}ok(error)
	error=false;try{'' + t8}catch(e){error = true}ok(error)
	error=false;try{+ t8}catch(e){error = true}ok(error)
	error=false;try{String(t8)}catch(e){error = true}ok(error)

})()
})() 


#--------------------------------------------------------------------#
# Tests 45-7: Class bindings: inheritance

$j->bind_class(
	package => 'HumptyDumpty',
	isa => 'String',
);

is refaddr $j->{String}{prototype},
   refaddr $j->upgrade(bless [], 'HumptyDumpty')->prototype->prototype,
   'isa => "String"';

$j->bind_class(
	package => 'JackHorner',
	isa => $j->{Array}{prototype},
);

is refaddr $j->{Array}{prototype},
   refaddr $j->upgrade(bless [], 'JackHorner')->prototype->prototype,
   'isa => $protoobject';

$j->bind_class( # Test 88 also relies on this binding, so make sure it
                # gets another if this is deleted.
	package => 'RunningOutOfWeirdIdeas',
	isa => undef
);

is_deeply $j->upgrade(bless [], 'RunningOutOfWeirdIdeas')->prototype
	->prototype, undef, 'isa => undef';

#--------------------------------------------------------------------#
# Test 48: Class bindings: proxy caching

{
	my $thing = bless [], 'RunningOutOfWeirdIdeas';
	is refaddr $j->upgrade($thing), refaddr $j->upgrade($thing),
		'proxy caching';
} 


#--------------------------------------------------------------------#
# Tests 49-88: Class bindings: properties

$j->{is} ||= \&is;
$j->{ok} ||= \&ok;

{
	package PropsArray;  # tests 'props => \@array'
	sub knew { bless [] }
	my($thing1,$thing2,$thing3,$thing4);
	sub prop1 { ++$thing1 . ' $a_' . ref($_[0]) . '->prop1' }

t/bind_class.t  view on Meta::CPAN

	array 2
	hash 2.5
) ;

{
	use Symbol;
	bless my $g = gensym, 'Arrash';
	${*$g}{length} = 17;
	${*$g}{0} = '4 jolly nerds';
	${*$g}{doodad} = '3 henchmen';

	my $ugh = $j->upgrade($g);

	is $ugh->{0}, '4 jolly nerds';
	is $ugh->{length}, 0;
	$ugh->{length} = 17;
	is @{*$g}, 17;
	is $ugh->{doodad}, '3 henchmen';

	delete ${*$g}{0};
	delete ${*$g}{doodad};

	is $ugh->{0}, 'undefined';
	$ugh->{length} = 0;
	is $ugh->{0}, 'something';
	is $ugh->{doodad}, 'weird';

	is join(':-)', sort keys %$ugh), '0:-)doodad:-)length';
}

# Bug in JE 0.036 and earlier: array- and hash-like classes do not over-
# ride exists to reflect the extra properties:
{
 my $a = $j->upgrade(bless \my %a, 'Hush!');
 $a{frext} = "ghed";
 ok $a->exists('frext'), 'exists works on hash elements';
 ok exists $$a{frext}, 'exists works on hash elements (tie interface)';
}


delete $j->{Object}{$_} for qw _0 doodad_;

#--------------------------------------------------------------------#
# Tests 126-69 (17+17+9+1=44): Class bindings: method return types

sub ___::AUTOLOAD{scalar reverse $___::AUTOLOAD}
sub ___::oof{}
sub ___::ooph{}

$j->bind_class(
	name => '___',
	methods => [qw[ foo:Number ___::bar ___::baz:null oof:null ]],
	static_methods =>[qw[FOO:Number ___::BAR ___::BAZ:null oof:null]],
	to_primitive => 'prim:Boolean',
	props => [qw[phoo:Number ___::barr ___::bazz:null ooph:null ]],
	static_props=>[qw[PHOO:Number ___::BARR ___::BAZZ:null ooph:null]],
);

{ # 17 tests here:
	my $foo = $j->upgrade(bless[],'___');
	is $foo->method('foo'), 'NaN', 'methods => [method:func]';
	is $foo->method('___::bar'), 'rab::___',
		'methods => [Package::method]';
	is $foo->method('___::baz'), 'zab::___',
		'methods => [Package::method:thing]';
	is $foo->method('oof'), 'null', 'methods => [method:null]';

	my $con#structor
		= $j->{___};
	is $con->method('FOO'), 'NaN', 'static_methods => [method:func]';
	is $con->method('___::BAR'), 'RAB::___',
		'static_methods => [Package::method]';
	is $con->method('___::BAZ'), 'ZAB::___',
		'static_methods => [Package::method:thing]';
	is $con->method('oof'), 'null', 'static_methods => [method:null]';

	is $foo->to_primitive, 'true', 'to_primtive => method:func';

	is $foo->{phoo}, 'NaN', 'props => [method:func]';
	is $foo->{'___::barr'}, 'rrab::___',
		'props => [Package::method]';
	is $foo->{'___::bazz'}, 'zzab::___',
		'props => [Package::method:thing]';
	is $foo->{ooph}, 'null', 'props => [method:null]';

	is $con->{PHOO}, 'NaN', 'static_props => [method:func]';
	is $con->{'___::BARR'}, 'RRAB::___',
		'static_props => [Package::method]';
	is $con->{'___::BAZZ'}, 'ZZAB::___',
		'static_props => [Package::method:thing]';
	is $con->{ooph}, 'null', 'static_props => [method:null]';

}

sub __::AUTOLOAD{scalar reverse $__'AUTOLOAD}
sub __::oof{}

$j->bind_class(
	name => '__',
	methods => {qw{
		phew foo:Number
		bare __::bar
		bass __::baz:null
		poof oof:null
	}},
	static_methods => {qw{
		PHEW foo:Number
		BARE __::BAR
		BASS __::BAZ:null
		POOF oof:null
	}},
	to_primitive => '__::prim:null',
	props => {qw{
		hati foo:Number
		uraa __::barr
		orut __::bazz:null
		hwha oof:null
	}},
	static_props => {qw{
		AHTI foo:Number
		URAI __::BARR
		ORUT __::BAZZ:null
		WHAT oof:null
	}},
);

{ # 17 tests here:
	my $foo = $j->upgrade(bless[],'__');
	is $foo->method('phew'), 'NaN',
		'methods => {name => method:func}';
	is $foo->method('bare'), 'rab::__',
		'methods => {name => Package::method}';
	is $foo->method('bass'), 'zab::__',
		'methods => {name => Package::method:thing}';
	is $foo->method('poof'), 'null',
		'methods => {name => method:null}';

	my $con#structor
		= $j->{__};
	is $con->method('PHEW'), 'NaN',
		'static_methods => {name => method:func}';
	is $con->method('BARE'), 'RAB::__',
		'static_methods => {name => Package::method}';
	is $con->method('BASS'), 'ZAB::__',
		'static_methods => {name => Package::method:thing}';
	is $con->method('POOF'), 'null',
		'static_methods => {name => method:null}';

	is $foo->to_primitive, 'mirp::__',
		'to_primtive => Pack::method:null';

	is $foo->{hati}, 'NaN', 'props => {name => method:func}';
	is $foo->{'uraa'}, 'rrab::__',
		'props => {name => Package::method}';
	is $foo->{'orut'}, 'zzab::__',
		'props => {name => Package::method:thing}';
	is $foo->{hwha}, 'null', 'props => {mname => ethod:null}';

	is $con->{AHTI}, 'NaN', 'static_props => {name => method:func}';
	is $con->{'URAI'}, 'RRAB::__',
		'static_props => {name => Package::method}';
	is $con->{'ORUT'}, 'ZZAB::__',
		'static_props => {name => Package::method:thing}';
	is $con->{WHAT}, 'null', 'static_props => {name => method:null}';

}

sub _::AUTOLOAD{scalar reverse $_'AUTOLOAD}
sub _::oof{}

$j->bind_class(
	name => '_',
	to_primitive => '_::prim',
	props => {
		hati => { fetch => 'foo:Number' },
		uraa => { fetch => '_::bar'     },
		orut => { fetch => '_::baz:null'},
		hwha => { fetch => 'oof:null'   },
	},
	static_props => {
		AHTI => { fetch => 'foo:Number' },
		URAI => { fetch => '_::BAR'     },
		ORUT => { fetch => '_::BAZ:null'},
		WHAT => { fetch => 'oof:null'   },
	},
);

{ # 9 tests here:
	my $foo = $j->upgrade(bless[],'_');

	is $foo->to_primitive, 'mirp::_',
		'to_primtive => Pack::method:null';

	is $foo->{hati}, 'NaN',
		'props => {name => {fetch => method:func}}';
	is $foo->{'uraa'}, 'rab::_',
		'props => {name => {fetch => Package::method}}';
	is $foo->{'orut'}, 'zab::_',
		'props => {name => {fetch => Package::method:thing}}';
	is $foo->{hwha}, 'null',
		'props => {mname => {fetch => ethod:null}}';

	my $con#structor
		= $j->{_};
	is $con->{AHTI}, 'NaN',
		'static_props => {name => {fetch => method:func}}';
	is $con->{'URAI'}, 'RAB::_',
		'static_props => {name => {fetch => Package::method}}';
	is $con->{'ORUT'}, 'ZAB::_',
		'static_props => {name => {fetch => Pack::method:thing}}';
	is $con->{WHAT}, 'null',
		'static_props => {name => {fetch => method:null}}';

}


sub ____::oof{}

$j->bind_class(
	name => '____',
	to_primitive => 'oof:null',
);

# 1 test here:
is $j->upgrade(bless[],'____')->to_primitive, 'null',
	'to_primitive => method:null';


#--------------------------------------------------------------------#
# Test 170: Class bindings: inherited property [gs]etters

$j->bind_class(package => 'base_class',
               props => { property => sub { ${+shift} } });
$j->bind_class(package => 'subclarce', isa => 'base_class');

{
	bless my $x = \(my $y = 'fo'), 'subclarce';
	is $j->upgrade($x)->{property}, 'fo',
		'inhertied property [gs]etters';
}

#--------------------------------------------------------------------#
# Tests 171-6: Class bindings: respect of Perl's overloading

{package ov; use overload '""' => sub { 43 }}
$j->bind_class(name => 'ov');
$j->bind_class(name => 'un');
is ($j->upgrade(bless [], 'ov')->to_string, 43,
	'Perl\'s string overloading in JS');
is ($j->upgrade(bless [], 'ov')->to_number, 43,
	'Perl\'s number overloading in JS');
is ($j->upgrade(bless [], 'ov')->to_primitive, 43,
	'Perl\'s overloading in JS');
is ($j->upgrade(bless [], 'un')->to_string, '[object un]',
	'Perl\'s stringification ignored without overloading');
is ($j->upgrade(bless [], 'un')->to_number, 'NaN',
	'Perl\'s numbification ignored without overloading');
is ($j->upgrade(bless [], 'un')->to_primitive, '[object un]',
	'Perl\'s stringification ignored without overloading (2)');


#--------------------------------------------------------------------#
# Tests 177-98: Scalar context for methods/coderefs passed to bind_class

sub scalartest::ten { 3, 10 }
sub scalartest::three { 7, 3 }
sub scalartest::twelve { 11, 12 }

$j->bind_class(
	package => 'scalartest',
	constructor => sub { (9, 10) },
	methods => ['twelve:Number'],
	static_methods => ['twelve:Number'],
	props => ['ten:Number', 'three'],
	static_props => ['ten:Number', 'three'],
);
is $j->eval('new scalartest'), 10,
	'scalar context for coderef constructor';
is $j->upgrade(bless[], 'scalartest')->method('twelve'), 12,
	'scalar context for typed method specified in array';
is $j->{scalartest}->method('twelve'), 12,
	'scalar context for typed static method specified in array';
is $j->upgrade(bless[], 'scalartest')->prop('ten'), 10,
	'scalar context for typed method-name prop specified in array';
is $j->upgrade(bless[], 'scalartest')->prop('three'), 3,
	'scalar context for untyped method-name prop specified in array';
is $j->{scalartest}->{ten}, 10,
    'scalar context for typed static method-name prop specified in array';
is $j->{scalartest}->{three}, 3,
  'scalar context for untyped static method-name prop specified in array';

$j->bind_class(
	package => 'scalartest',
	constructor => 'twelve',
	methods => { method => 'twelve:Number' },
	static_methods => { method => 'twelve:Number' },
	props => {
		prop => { fetch => sub { 2, 3 } },
		prop2 => { fetch => 'ten:Number' },
		prop3 => { fetch => 'ten' },
		prop4 => sub { 3, 4 },
		prop5 => 'ten:Number',
		prop6 => 'ten',
	},
	static_props => {
		prop => { fetch => sub { 2, 3 } },
		prop2 => { fetch => 'ten:Number' },
		prop3 => { fetch => 'ten' },
		prop4 => sub { 3, 4 },
		prop5 => 'ten:Number',
		prop6 => 'ten',
	},
);
is $j->eval('new scalartest'), 12,
	'scalar context for method constructor';
is $j->upgrade(bless[], 'scalartest')->method('method'), 12,



( run in 2.700 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )