1
0
Fork 0

Visibility object is now encapsulated in symbol key

Note that this patch temporarily breaks encapsulation via
ClassBuilder.___$$privsym$$ to expose necessary internal details to Trait;
this will be resolved.
protolib
Mike Gerwitz 2014-07-07 00:11:58 -04:00
parent a35a9c6ed3
commit 13b0bd2fb3
4 changed files with 39 additions and 26 deletions

View File

@ -233,11 +233,11 @@ exports.getForcedPublicMethods = function()
* *
* @param {Function|Object} cls class from which to retrieve metadata * @param {Function|Object} cls class from which to retrieve metadata
* *
* @return {__class_meta} * @return {__class_meta} or null if unavailable
*/ */
exports.getMeta = function( cls ) exports.getMeta = function( cls )
{ {
return ( cls[ _priv ] || {} ).meta || {}; return ( cls[ _priv ] || {} ).meta || null;
} }
@ -338,7 +338,7 @@ exports.prototype.build = function extend( _, __ )
props: this._memberBuilder.initMembers(), props: this._memberBuilder.initMembers(),
}, },
meta = exports.getMeta( base ), meta = exports.getMeta( base ) || {},
abstract_methods = abstract_methods =
util.clone( meta.abstractMethods ) util.clone( meta.abstractMethods )
@ -387,7 +387,7 @@ exports.prototype.build = function extend( _, __ )
// properties initialized by the ctor are implicitly public; otherwise, // properties initialized by the ctor are implicitly public; otherwise,
// proxying will fail to take place // proxying will fail to take place
// TODO: see Class.isA TODO // TODO: see Class.isA TODO
if ( prototype.___$$vis$$ === undefined ) if ( ( prototype[ _priv ] || {} ).vis === undefined )
{ {
this._discoverProtoProps( prototype, prop_init ); this._discoverProtoProps( prototype, prop_init );
} }
@ -1006,7 +1006,8 @@ exports.prototype._attachPropInit = function(
inherit = !!inherit; inherit = !!inherit;
var iid = this.__iid, var iid = this.__iid,
parent = prototype.___$$parent$$; parent = prototype.___$$parent$$,
vis = this[ _priv ].vis;
// first initialize the parent's properties, so that ours will overwrite // first initialize the parent's properties, so that ours will overwrite
// them // them
@ -1022,7 +1023,7 @@ exports.prototype._attachPropInit = function(
// this will return our property proxy, if supported by our environment, // this will return our property proxy, if supported by our environment,
// otherwise just a normal object with everything merged in // otherwise just a normal object with everything merged in
var inst_props = _self._visFactory.createPropProxy( var inst_props = _self._visFactory.createPropProxy(
this, this.___$$vis$$, properties[ 'public' ] this, vis, properties[ 'public' ]
); );
// Copies all public and protected members into inst_props and stores // Copies all public and protected members into inst_props and stores
@ -1030,7 +1031,7 @@ exports.prototype._attachPropInit = function(
// chain and is returned. This is stored in a property referenced by the // chain and is returned. This is stored in a property referenced by the
// class id, so that the private members can be swapped on each method // class id, so that the private members can be swapped on each method
// request, depending on calling context. // request, depending on calling context.
var vis = this.___$$vis$$[ cid ] = _self._visFactory.setup( var vis = vis[ cid ] = _self._visFactory.setup(
inst_props, properties, members inst_props, properties, members
); );
@ -1232,6 +1233,10 @@ exports.prototype.attachStatic = function( ctor, members, base, inheriting )
} }
// FIXME: this is *temporary* during refactoring!
module.exports.___$$privsym$$ = _priv;
/** /**
* Initializes class metadata for the given class * Initializes class metadata for the given class
* *
@ -1325,8 +1330,12 @@ function initInstance( instance )
var prot = function() {}; var prot = function() {};
prot.prototype = instance; prot.prototype = instance;
// initialize our *own* private metadata store; do not use the
// prototype's
instance[ _priv ] = {};
// add the visibility objects to the data object for this class instance // add the visibility objects to the data object for this class instance
instance.___$$vis$$ = new prot(); instance[ _priv ].vis = new prot();
} }
@ -1380,9 +1389,10 @@ exports.getMethodInstance = function( inst, cid )
} }
var iid = inst.__iid, var iid = inst.__iid,
data = inst.___$$vis$$; priv = inst[ _priv ],
data;
return ( iid && data ) return ( iid && priv && ( data = priv.vis ) )
? data[ cid ] ? data[ cid ]
: null : null
; ;

View File

@ -680,6 +680,9 @@ function addTraitInst( T, dfn, tc, base )
*/ */
function tctor( tc, base ) function tctor( tc, base )
{ {
// FIXME: this is temporary during refactoring!
var cbpriv = ClassBuilder.___$$privsym$$;
// instantiate all traits and assign the object to their // instantiate all traits and assign the object to their
// respective fields // respective fields
for ( var t in tc ) for ( var t in tc )
@ -693,7 +696,7 @@ function tctor( tc, base )
// (but not private); in return, we will use its own protected // (but not private); in return, we will use its own protected
// visibility object to gain access to its protected members...quite // visibility object to gain access to its protected members...quite
// the intimate relationship // the intimate relationship
this[ f ] = C( base, this.___$$vis$$ ).___$$vis$$; this[ f ] = C( base, this[ cbpriv ].vis )[ cbpriv ].vis;
} }
// if we are a subtype, be sure to initialize our parent's traits // if we are a subtype, be sure to initialize our parent's traits

View File

@ -169,6 +169,8 @@ var _dummyinst = { constructor: { prototype: {} } };
/** /**
* Determines whether the provided object is a class created through ease.js * Determines whether the provided object is a class created through ease.js
* *
* TODO: delegate to ClassBuilder
*
* @param {Object} obj object to test * @param {Object} obj object to test
* *
* @return {boolean} true if class (created through ease.js), otherwise false * @return {boolean} true if class (created through ease.js), otherwise false
@ -182,10 +184,11 @@ module.exports.isClass = function( obj )
return false; return false;
} }
// TODO: this just checks one of many internal fields; we need something var meta = ClassBuilder.getMeta( obj );
// more formal (cannot use a strict ClassBase check because it will fail
// when extending prototypes) // TODO: we're checking a random field on the meta object; do something
return ( ( obj.prototype.___$$vis$$ !== undefined ) // proper
return ( ( ( meta !== null ) && meta.implemented )
|| ( obj.prototype instanceof ClassBuilder.ClassBase ) ) || ( obj.prototype instanceof ClassBuilder.ClassBase ) )
? true ? true
: false : false
@ -197,6 +200,8 @@ module.exports.isClass = function( obj )
* Determines whether the provided object is an instance of a class created * Determines whether the provided object is an instance of a class created
* through ease.js * through ease.js
* *
* TODO: delegate to ClassBuilder
*
* @param {Object} obj object to test * @param {Object} obj object to test
* *
* @return {boolean} true if instance of class (created through ease.js), * @return {boolean} true if instance of class (created through ease.js),
@ -206,16 +211,8 @@ module.exports.isClassInstance = function( obj )
{ {
obj = obj || _dummyinst; obj = obj || _dummyinst;
if ( !obj.constructor || !obj.constructor.prototype ) // if the constructor is a class, then we must be an instance!
{ return module.exports.isClass( obj.constructor );
return false;
}
// TODO: see isClass TODO
return ( ( obj.constructor.prototype.___$$vis$$ !== undefined )
|| ( obj instanceof ClassBuilder.ClassBase ) )
? true
: false;
}; };

View File

@ -492,10 +492,13 @@ function attachInstanceOf( iface )
*/ */
function _isInstanceOf( type, instance ) function _isInstanceOf( type, instance )
{ {
// we are interested in the class's metadata, not the instance's
var proto = instance.constructor;
// if no metadata are available, then our remaining checks cannot be // if no metadata are available, then our remaining checks cannot be
// performed // performed
var meta; var meta;
if ( !instance.__cid || !( meta = ClassBuilder.getMeta( instance ) ) ) if ( !instance.__cid || !( meta = ClassBuilder.getMeta( proto ) ) )
{ {
return false; return false;
} }