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
*
* @return {__class_meta}
* @return {__class_meta} or null if unavailable
*/
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(),
},
meta = exports.getMeta( base ),
meta = exports.getMeta( base ) || {},
abstract_methods =
util.clone( meta.abstractMethods )
@ -387,7 +387,7 @@ exports.prototype.build = function extend( _, __ )
// properties initialized by the ctor are implicitly public; otherwise,
// proxying will fail to take place
// TODO: see Class.isA TODO
if ( prototype.___$$vis$$ === undefined )
if ( ( prototype[ _priv ] || {} ).vis === undefined )
{
this._discoverProtoProps( prototype, prop_init );
}
@ -1006,7 +1006,8 @@ exports.prototype._attachPropInit = function(
inherit = !!inherit;
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
// them
@ -1022,7 +1023,7 @@ exports.prototype._attachPropInit = function(
// this will return our property proxy, if supported by our environment,
// otherwise just a normal object with everything merged in
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
@ -1030,7 +1031,7 @@ exports.prototype._attachPropInit = function(
// 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
// request, depending on calling context.
var vis = this.___$$vis$$[ cid ] = _self._visFactory.setup(
var vis = vis[ cid ] = _self._visFactory.setup(
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
*
@ -1325,8 +1330,12 @@ function initInstance( instance )
var prot = function() {};
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
instance.___$$vis$$ = new prot();
instance[ _priv ].vis = new prot();
}
@ -1380,9 +1389,10 @@ exports.getMethodInstance = function( inst, cid )
}
var iid = inst.__iid,
data = inst.___$$vis$$;
priv = inst[ _priv ],
data;
return ( iid && data )
return ( iid && priv && ( data = priv.vis ) )
? data[ cid ]
: null
;

View File

@ -680,6 +680,9 @@ function addTraitInst( T, dfn, 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
// respective fields
for ( var t in tc )
@ -693,7 +696,7 @@ function tctor( tc, base )
// (but not private); in return, we will use its own protected
// visibility object to gain access to its protected members...quite
// 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

View File

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

View File

@ -492,10 +492,13 @@ function attachInstanceOf( iface )
*/
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
// performed
var meta;
if ( !instance.__cid || !( meta = ClassBuilder.getMeta( instance ) ) )
if ( !instance.__cid || !( meta = ClassBuilder.getMeta( proto ) ) )
{
return false;
}