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
parent
a35a9c6ed3
commit
13b0bd2fb3
|
@ -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
|
||||||
;
|
;
|
||||||
|
|
|
@ -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
|
||||||
|
|
25
lib/class.js
25
lib/class.js
|
@ -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;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue