Began encapsulating internal metadata with symbols
This is a move to solve a couple issues: - We shouldn't be adding a ton of non-enumerable stuff to an object--- defineProperty is slow; and - One object containing all internal data (at least in general; more on that later) makes ignoring it, copying it, or otherwise operating upon it a much easier and cleaner task.protolib
commit
1458d79ee1
|
@ -25,8 +25,8 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var util = require( './util' ),
|
var util = require( './util' ),
|
||||||
warn = require( './warn' ),
|
Warning = require( './warn' ).Warning,
|
||||||
Warning = warn.Warning,
|
Symbol = require( './util/Symbol' ),
|
||||||
|
|
||||||
hasOwn = Object.prototype.hasOwnProperty,
|
hasOwn = Object.prototype.hasOwnProperty,
|
||||||
|
|
||||||
|
@ -74,7 +74,18 @@ var util = require( './util' ),
|
||||||
'__construct': true,
|
'__construct': true,
|
||||||
'toString': true,
|
'toString': true,
|
||||||
'__toString': true,
|
'__toString': true,
|
||||||
};
|
},
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Symbol used to encapsulate internal data
|
||||||
|
*
|
||||||
|
* Note that this is intentionally generated *outside* the ClassBuilder
|
||||||
|
* instance; this ensures that it is properly encapsulated and will not
|
||||||
|
* be exposed on the Classbuilder instance (which would defeat the
|
||||||
|
* purpose).
|
||||||
|
*/
|
||||||
|
_priv = Symbol()
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -90,15 +101,23 @@ var util = require( './util' ),
|
||||||
* @constructor
|
* @constructor
|
||||||
*/
|
*/
|
||||||
module.exports = exports =
|
module.exports = exports =
|
||||||
function ClassBuilder( member_builder, visibility_factory )
|
function ClassBuilder( warn_handler, member_builder, visibility_factory )
|
||||||
{
|
{
|
||||||
// allow ommitting the 'new' keyword
|
// allow ommitting the 'new' keyword
|
||||||
if ( !( this instanceof exports ) )
|
if ( !( this instanceof exports ) )
|
||||||
{
|
{
|
||||||
// module.exports for Closure Compiler
|
// module.exports for Closure Compiler
|
||||||
return new module.exports( member_builder, visibility_factory );
|
return new module.exports(
|
||||||
|
warn_handler, member_builder, visibility_factory
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determines how warnings should be handled
|
||||||
|
* @type {WarningHandler}
|
||||||
|
*/
|
||||||
|
this._warnHandler = warn_handler;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for building class members
|
* Used for building class members
|
||||||
* @type {Object}
|
* @type {Object}
|
||||||
|
@ -214,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.___$$meta$$ || {};
|
return ( cls[ _priv ] || {} ).meta || null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -319,12 +338,14 @@ exports.prototype.build = function extend( _, __ )
|
||||||
props: this._memberBuilder.initMembers(),
|
props: this._memberBuilder.initMembers(),
|
||||||
},
|
},
|
||||||
|
|
||||||
|
meta = exports.getMeta( base ) || {},
|
||||||
|
|
||||||
abstract_methods =
|
abstract_methods =
|
||||||
util.clone( exports.getMeta( base ).abstractMethods )
|
util.clone( meta.abstractMethods )
|
||||||
|| { __length: 0 },
|
|| { __length: 0 },
|
||||||
|
|
||||||
virtual_members =
|
virtual_members =
|
||||||
util.clone( exports.getMeta( base ).virtualMembers )
|
util.clone( meta.virtualMembers )
|
||||||
|| {}
|
|| {}
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -333,7 +354,7 @@ exports.prototype.build = function extend( _, __ )
|
||||||
{
|
{
|
||||||
throw Error(
|
throw Error(
|
||||||
"Cannot extend final class " +
|
"Cannot extend final class " +
|
||||||
( base.___$$meta$$.name || '(anonymous)' )
|
( base[ _priv ].meta.name || '(anonymous)' )
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -366,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 );
|
||||||
}
|
}
|
||||||
|
@ -396,7 +417,7 @@ exports.prototype.build = function extend( _, __ )
|
||||||
// intercept warnings /only/
|
// intercept warnings /only/
|
||||||
if ( e instanceof Warning )
|
if ( e instanceof Warning )
|
||||||
{
|
{
|
||||||
warn.handle( e );
|
this._warnHandler.handle( e );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -790,16 +811,19 @@ function validateAbstract( ctor, cname, abstract_methods, auto )
|
||||||
*/
|
*/
|
||||||
exports.prototype.createCtor = function( cname, abstract_methods, members )
|
exports.prototype.createCtor = function( cname, abstract_methods, members )
|
||||||
{
|
{
|
||||||
// concrete class
|
var new_class;
|
||||||
|
|
||||||
if ( abstract_methods.__length === 0 )
|
if ( abstract_methods.__length === 0 )
|
||||||
{
|
{
|
||||||
return this.createConcreteCtor( cname, members );
|
new_class = this.createConcreteCtor( cname, members );
|
||||||
}
|
}
|
||||||
// abstract class
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
return this.createAbstractCtor( cname );
|
new_class = this.createAbstractCtor( cname );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
util.defineSecureProp( new_class, _priv, {} );
|
||||||
|
return new_class;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -858,7 +882,9 @@ exports.prototype.createConcreteCtor = function( cname, members )
|
||||||
// handle internal trait initialization logic, if provided
|
// handle internal trait initialization logic, if provided
|
||||||
if ( typeof this.___$$tctor$$ === 'function' )
|
if ( typeof this.___$$tctor$$ === 'function' )
|
||||||
{
|
{
|
||||||
this.___$$tctor$$.call( this );
|
// FIXME: we're exposing _priv to something that can be
|
||||||
|
// malicously set by the user; encapsulate tctor
|
||||||
|
this.___$$tctor$$.call( this, _priv );
|
||||||
}
|
}
|
||||||
|
|
||||||
// call the constructor, if one was provided
|
// call the constructor, if one was provided
|
||||||
|
@ -982,7 +1008,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
|
||||||
|
@ -998,7 +1025,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
|
||||||
|
@ -1006,7 +1033,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
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -1230,21 +1257,13 @@ function createMeta( func, cparent )
|
||||||
// copy the parent prototype's metadata if it exists (inherit metadata)
|
// copy the parent prototype's metadata if it exists (inherit metadata)
|
||||||
if ( parent_meta )
|
if ( parent_meta )
|
||||||
{
|
{
|
||||||
func.___$$meta$$ = util.clone( parent_meta, true );
|
return func[ _priv ].meta = util.clone( parent_meta, true );
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
// create empty
|
// create empty
|
||||||
func.___$$meta$$ = {
|
return func[ _priv ].meta = {
|
||||||
implemented: [],
|
implemented: [],
|
||||||
};
|
};
|
||||||
}
|
|
||||||
|
|
||||||
// store the metadata in the prototype as well (inconsiderable overhead;
|
|
||||||
// it's just a reference)
|
|
||||||
func.prototype.___$$meta$$ = func.___$$meta$$;
|
|
||||||
|
|
||||||
return func.___$$meta$$;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1295,8 +1314,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
|
||||||
|
util.defineSecureProp( 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();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -1350,9 +1373,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
|
||||||
;
|
;
|
||||||
|
|
|
@ -30,7 +30,6 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
var util = require( './util' ),
|
var util = require( './util' ),
|
||||||
Warning = require( './warn' ).Warning,
|
|
||||||
visibility = [ 'public', 'protected', 'private' ]
|
visibility = [ 'public', 'protected', 'private' ]
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
17
lib/Trait.js
17
lib/Trait.js
|
@ -673,12 +673,19 @@ function addTraitInst( T, dfn, tc, base )
|
||||||
* This will lazily create the concrete trait class if it does not already
|
* This will lazily create the concrete trait class if it does not already
|
||||||
* exist, which saves work if the trait is never used.
|
* exist, which saves work if the trait is never used.
|
||||||
*
|
*
|
||||||
|
* Note that the private symbol used to encapsulate class data must be
|
||||||
|
* passed to this function to provide us access to implementation details
|
||||||
|
* that we really shouldn't be messing around with. :) In particular, we
|
||||||
|
* need access to the protected visibility object, and there is [currently]
|
||||||
|
* no API for doing so.
|
||||||
|
*
|
||||||
* @param {Object} tc trait class list
|
* @param {Object} tc trait class list
|
||||||
* @param {Class} base target supertype
|
* @param {Class} base target supertype
|
||||||
|
* @param {Symbol} privsym symbol used as key for encapsulated data
|
||||||
*
|
*
|
||||||
* @return {undefined}
|
* @return {undefined}
|
||||||
*/
|
*/
|
||||||
function tctor( tc, base )
|
function tctor( tc, base, privsym )
|
||||||
{
|
{
|
||||||
// instantiate all traits and assign the object to their
|
// instantiate all traits and assign the object to their
|
||||||
// respective fields
|
// respective fields
|
||||||
|
@ -693,11 +700,11 @@ 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[ privsym ].vis )[ privsym ].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
|
||||||
this.__super && this.__super();
|
this.__super && this.__super( privsym );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -714,9 +721,9 @@ function tctor( tc, base )
|
||||||
*/
|
*/
|
||||||
function createTctor( tc, base )
|
function createTctor( tc, base )
|
||||||
{
|
{
|
||||||
return function()
|
return function( privsym )
|
||||||
{
|
{
|
||||||
return tctor.call( this, tc, base );
|
return tctor.call( this, tc, base, privsym );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
42
lib/class.js
42
lib/class.js
|
@ -19,16 +19,31 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Console to use for logging
|
||||||
|
*
|
||||||
|
* This reference allows an alternative console to be used. Must contain
|
||||||
|
* warn() or log() methods.
|
||||||
|
*
|
||||||
|
* TODO: This needs to be moved into a facade, once more refactoring can be
|
||||||
|
* done; it was moved out of warn during its refactoring.
|
||||||
|
*
|
||||||
|
* @type {Object}
|
||||||
|
*/
|
||||||
|
var _console = ( typeof console !== 'undefined' ) ? console : undefined;
|
||||||
|
|
||||||
var util = require( './util' ),
|
var util = require( './util' ),
|
||||||
ClassBuilder = require( './ClassBuilder' ),
|
ClassBuilder = require( './ClassBuilder' ),
|
||||||
|
|
||||||
warn = require( './warn' ),
|
warn = require( './warn' ),
|
||||||
Warning = warn.Warning,
|
Warning = warn.Warning,
|
||||||
|
log_handler = warn.LogHandler( _console ),
|
||||||
|
|
||||||
MethodWrapperFactory = require( './MethodWrapperFactory' ),
|
MethodWrapperFactory = require( './MethodWrapperFactory' ),
|
||||||
wrappers = require( './MethodWrappers' ).standard,
|
wrappers = require( './MethodWrappers' ).standard,
|
||||||
|
|
||||||
class_builder = ClassBuilder(
|
class_builder = ClassBuilder(
|
||||||
|
log_handler,
|
||||||
require( './MemberBuilder' )(
|
require( './MemberBuilder' )(
|
||||||
MethodWrapperFactory( wrappers.wrapNew ),
|
MethodWrapperFactory( wrappers.wrapNew ),
|
||||||
MethodWrapperFactory( wrappers.wrapOverride ),
|
MethodWrapperFactory( wrappers.wrapOverride ),
|
||||||
|
@ -36,7 +51,7 @@ var util = require( './util' ),
|
||||||
require( './MemberBuilderValidator' )(
|
require( './MemberBuilderValidator' )(
|
||||||
function( warning )
|
function( warning )
|
||||||
{
|
{
|
||||||
warn.handle( Warning( warning ) );
|
log_handler.handle( Warning( warning ) );
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
),
|
),
|
||||||
|
@ -154,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
|
||||||
|
@ -167,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
|
||||||
|
@ -182,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),
|
||||||
|
@ -191,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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,9 @@ var can_define_prop = ( function()
|
||||||
} )();
|
} )();
|
||||||
|
|
||||||
|
|
||||||
|
exports.Global = require( './util/Global' );
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Freezes an object if freezing is supported
|
* Freezes an object if freezing is supported
|
||||||
*
|
*
|
||||||
|
|
|
@ -0,0 +1,120 @@
|
||||||
|
/**
|
||||||
|
* Global scope handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// retrieve global scope; works with ES5 strict mode
|
||||||
|
(0,eval)( 'var _the_global=this' );
|
||||||
|
|
||||||
|
// prototype to allow us to augment the global scope for our own purposes
|
||||||
|
// without polluting the global scope
|
||||||
|
function _G() {}
|
||||||
|
_G.prototype = _the_global;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides access to and augmentation of global variables
|
||||||
|
*
|
||||||
|
* This provides a static method to consistently provide access to the
|
||||||
|
* object representing the global scope, regardless of environment. Through
|
||||||
|
* instantiation, its API permits augmenting a local object whose prototype
|
||||||
|
* is the global scope, providing alternatives to variables that do not
|
||||||
|
* exist.
|
||||||
|
*/
|
||||||
|
function Global()
|
||||||
|
{
|
||||||
|
// allows omitting `new` keyword, consistent with ease.js style
|
||||||
|
if ( !( this instanceof Global ) )
|
||||||
|
{
|
||||||
|
return new Global();
|
||||||
|
}
|
||||||
|
|
||||||
|
// allows us to extend the global object without actually polluting the
|
||||||
|
// global scope
|
||||||
|
this._global = new _G();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides consistent access to the global scope through all ECMAScript
|
||||||
|
* versions, for any root variable name, and works with ES5 strict mode.
|
||||||
|
*
|
||||||
|
* As an example, Node.js exposes the variable `root` to represent global
|
||||||
|
* scope, but browsers expose `window`. Further, ES5 strict mode will provde
|
||||||
|
* an error when checking whether `typeof SomeGlobalVar === 'undefined'`.
|
||||||
|
*
|
||||||
|
* @return {Object} global object
|
||||||
|
*/
|
||||||
|
Global.expose = function()
|
||||||
|
{
|
||||||
|
return _the_global;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Global.prototype = {
|
||||||
|
/**
|
||||||
|
* Provide a value for the provided global variable name if it is not
|
||||||
|
* defined
|
||||||
|
*
|
||||||
|
* A function returning the value to assign to NAME should be provided,
|
||||||
|
* ensuring that the alternative is never even evaluated unless it is
|
||||||
|
* needed.
|
||||||
|
*
|
||||||
|
* The global scope will not be polluted with this alternative;
|
||||||
|
* consequently, you must access the value using the `get` method.
|
||||||
|
*
|
||||||
|
* @param {string} name global variable name
|
||||||
|
* @param {function()} f function returning value to assign
|
||||||
|
*
|
||||||
|
* @return {Global} self
|
||||||
|
*/
|
||||||
|
provideAlt: function( name, f )
|
||||||
|
{
|
||||||
|
if ( typeof this._global[ name ] !== 'undefined' )
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this._global[ name ] = f();
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve global value or provided alternative
|
||||||
|
*
|
||||||
|
* This will take into account values provided via `provideAlt`; if no
|
||||||
|
* alternative was provided, the request will be deleagated to the
|
||||||
|
* global variable NAME, which may or may not be undefined.
|
||||||
|
*
|
||||||
|
* No error will be thrown if NAME is not globally defined.
|
||||||
|
*
|
||||||
|
* @param {string} name global variable name
|
||||||
|
*
|
||||||
|
* @return {*} value associated with global variable NAME or
|
||||||
|
* its provided alternative
|
||||||
|
*/
|
||||||
|
get: function( name )
|
||||||
|
{
|
||||||
|
return this._global[ name ];
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
module.exports = Global;
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
/**
|
||||||
|
* Forward-compatible subset of ES6 Symbol
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This is *not* intended to be a complete implementation; it merely
|
||||||
|
* performs what is needed for ease.js, preferring the benefits of the ES6
|
||||||
|
* Symbol implementation while falling back to sane ES5 and ES3 options.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// to be used if there is no global Symbol available
|
||||||
|
var FallbackSymbol = require( './symbol/FallbackSymbol' );
|
||||||
|
|
||||||
|
var _root = require( './Global' ).expose();
|
||||||
|
module.exports = _root.Symbol || FallbackSymbol;
|
||||||
|
|
|
@ -0,0 +1,88 @@
|
||||||
|
/**
|
||||||
|
* Forward-compatible subset of ES6 Symbol for pre-ES6 environments
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* This is *not* intended to be a complete implementation; it merely
|
||||||
|
* performs what is needed for ease.js. In particular, this pre-ES6
|
||||||
|
* implementation will simply generate a random string to be used as a key;
|
||||||
|
* the caller is expected to add the key to the destination object as
|
||||||
|
* non-enumerable, if supported by the environment.
|
||||||
|
*/
|
||||||
|
|
||||||
|
// ensures that, so long as these methods have not been overwritten by the
|
||||||
|
// time ease.js is loaded, we will maintain a proper reference
|
||||||
|
var _random = Math.random,
|
||||||
|
_floor = Math.floor;
|
||||||
|
|
||||||
|
// prefix used for all generated symbol strings (this string is highly
|
||||||
|
// unlikely to exist in practice); it will produce a string containing a
|
||||||
|
// non-printable ASCII character that is *not* the null byte
|
||||||
|
var _root = ' ' + String.fromCharCode(
|
||||||
|
_floor( _random() * 10 ) % 31 + 1
|
||||||
|
) + '$';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generate a pseudo-random string (with a common prefix) to be used as an
|
||||||
|
* object key
|
||||||
|
*
|
||||||
|
* The returned key is unique so long as Math.{random,floor} are reliable.
|
||||||
|
* This will be true so long as (1) the runtime provides a reliable
|
||||||
|
* implementation and (2) Math.{floor,random} have not been overwritten at
|
||||||
|
* the time that this module is loaded. This module stores an internal
|
||||||
|
* reference to this methods, so malicious code loaded after this module
|
||||||
|
* will not be able to compromise the return value.
|
||||||
|
*
|
||||||
|
* Note that the returned string is not wholly random: a common prefix is
|
||||||
|
* used to ensure that collisions with other keys on objects is highly
|
||||||
|
* unlikely; you should not rely on this behavior, though, as it is an
|
||||||
|
* implementation detail that may change in the future.
|
||||||
|
*
|
||||||
|
* @return {string} pseudo-random string with common prefix
|
||||||
|
*/
|
||||||
|
function FallbackSymbol()
|
||||||
|
{
|
||||||
|
if ( !( this instanceof FallbackSymbol ) )
|
||||||
|
{
|
||||||
|
return new FallbackSymbol();
|
||||||
|
}
|
||||||
|
|
||||||
|
this.___$$id$$ = ( _root + _floor( _random() * 1e8 ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
FallbackSymbol.prototype = {
|
||||||
|
/**
|
||||||
|
* Return random identifier
|
||||||
|
*
|
||||||
|
* This is convenient, as it allows us to both treat the symbol as an
|
||||||
|
* object of type FallbackSymbol and use the symbol as a key (since
|
||||||
|
* doing so will automatically call this method).
|
||||||
|
*
|
||||||
|
* @return {string} random identifier
|
||||||
|
*/
|
||||||
|
toString: function()
|
||||||
|
{
|
||||||
|
return this.___$$id$$;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = FallbackSymbol;
|
||||||
|
|
185
lib/warn.js
185
lib/warn.js
|
@ -1,7 +1,7 @@
|
||||||
/**
|
/**
|
||||||
* ease.js warning system
|
* ease.js warning system
|
||||||
*
|
*
|
||||||
* Copyright (C) 2011, 2012, 2013 Free Software Foundation, Inc.
|
* Copyright (C) 2011, 2012, 2013, 2014 Free Software Foundation, Inc.
|
||||||
*
|
*
|
||||||
* This file is part of GNU ease.js.
|
* This file is part of GNU ease.js.
|
||||||
*
|
*
|
||||||
|
@ -19,184 +19,11 @@
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/**
|
module.exports = {
|
||||||
* Active warning handler
|
Warning: require( './warn/Warning' ),
|
||||||
* @type {?function( Warning )}
|
|
||||||
*/
|
|
||||||
var _handler = null;
|
|
||||||
|
|
||||||
/**
|
DismissiveHandler: require( './warn/DismissiveHandler' ),
|
||||||
* Console to use for logging
|
LogHandler: require( './warn/LogHandler' ),
|
||||||
*
|
ThrowHandler: require( './warn/ThrowHandler' ),
|
||||||
* This reference allows an alternative console to be used. Must contain warn()
|
|
||||||
* or log() methods.
|
|
||||||
*
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
var _console = ( typeof console !== 'undefined' ) ? console : undefined;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Permits wrapping an exception as a warning
|
|
||||||
*
|
|
||||||
* Warnings are handled differently by the system, depending on the warning
|
|
||||||
* level that has been set.
|
|
||||||
*
|
|
||||||
* @param {Error} e exception (error) to wrap
|
|
||||||
*
|
|
||||||
* @return {Warning} new warning instance
|
|
||||||
*
|
|
||||||
* @constructor
|
|
||||||
*/
|
|
||||||
var Warning = exports.Warning = function( e )
|
|
||||||
{
|
|
||||||
// allow instantiation without use of 'new' keyword
|
|
||||||
if ( !( this instanceof Warning ) )
|
|
||||||
{
|
|
||||||
return new Warning( e );
|
|
||||||
}
|
|
||||||
|
|
||||||
// ensure we're wrapping an exception
|
|
||||||
if ( !( e instanceof Error ) )
|
|
||||||
{
|
|
||||||
throw TypeError( "Must provide exception to wrap" );
|
|
||||||
}
|
|
||||||
|
|
||||||
Error.prototype.constructor.call( this, e.message );
|
|
||||||
|
|
||||||
// copy over the message for convenience
|
|
||||||
this.message = e.message;
|
|
||||||
this.name = 'Warning';
|
|
||||||
this._error = e;
|
|
||||||
|
|
||||||
this.stack = e.stack &&
|
|
||||||
e.stack.replace( /^.*?\n+/,
|
|
||||||
this.name + ': ' + this.message + "\n"
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// ensures the closest compatibility...just be careful not to modify Warning's
|
|
||||||
// prototype
|
|
||||||
Warning.prototype = Error();
|
|
||||||
Warning.prototype.constructor = Warning;
|
|
||||||
Warning.prototype.name = 'Warning';
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the error wrapped by the warning
|
|
||||||
*
|
|
||||||
* @return {Error} wrapped error
|
|
||||||
*/
|
|
||||||
Warning.prototype.getError = function()
|
|
||||||
{
|
|
||||||
return this._error;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Core warning handlers
|
|
||||||
* @type {Object}
|
|
||||||
*/
|
|
||||||
exports.handlers = {
|
|
||||||
/**
|
|
||||||
* Logs message to console
|
|
||||||
*
|
|
||||||
* Will attempt to log using console.warn(), falling back to console.log()
|
|
||||||
* if necessary and aborting entirely if neither is available.
|
|
||||||
*
|
|
||||||
* This is useful as a default option to bring problems to the developer's
|
|
||||||
* attention without affecting the control flow of the software.
|
|
||||||
*
|
|
||||||
* @param {Warning} warning to log
|
|
||||||
*
|
|
||||||
* @return {undefined}
|
|
||||||
*/
|
|
||||||
log: function( warning )
|
|
||||||
{
|
|
||||||
var dest;
|
|
||||||
|
|
||||||
_console && ( dest = _console.warn || _console.log ) &&
|
|
||||||
dest.call( _console, ( 'Warning: ' + warning.message ) );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Throws the error associated with the warning
|
|
||||||
*
|
|
||||||
* This handler is useful for development and will ensure that problems are
|
|
||||||
* brought to the attention of the developer.
|
|
||||||
*
|
|
||||||
* @param {Warning} warning to log
|
|
||||||
*
|
|
||||||
* @return {undefined}
|
|
||||||
*/
|
|
||||||
throwError: function( warning )
|
|
||||||
{
|
|
||||||
throw warning.getError();
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Ignores warnings
|
|
||||||
*
|
|
||||||
* This is useful in a production environment where (a) warnings will affect
|
|
||||||
* the reputation of the software or (b) warnings may provide too much
|
|
||||||
* insight into the software. If using this option, you should always
|
|
||||||
* develop in a separate environment so that the system may bring warnings
|
|
||||||
* to your attention.
|
|
||||||
*
|
|
||||||
* @param {Warning} warning to log
|
|
||||||
*
|
|
||||||
* @return {undefined}
|
|
||||||
*/
|
|
||||||
dismiss: function( warning )
|
|
||||||
{
|
|
||||||
// do nothing
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the active warning handler
|
|
||||||
*
|
|
||||||
* You may use any of the predefined warning handlers or pass your own function.
|
|
||||||
*
|
|
||||||
* @param {function( Warning )} handler warning handler
|
|
||||||
*
|
|
||||||
* @return {undefined}
|
|
||||||
*/
|
|
||||||
exports.setHandler = function( handler )
|
|
||||||
{
|
|
||||||
_handler = handler;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Handles a warning using the active warning handler
|
|
||||||
*
|
|
||||||
* @param {Warning} warning warning to handle
|
|
||||||
*
|
|
||||||
* @return {undefined}
|
|
||||||
*/
|
|
||||||
exports.handle = function( warning )
|
|
||||||
{
|
|
||||||
_handler( warning );
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets active console
|
|
||||||
*
|
|
||||||
* @param {Object} console containing warn() or log() method
|
|
||||||
*
|
|
||||||
* @return {undefined}
|
|
||||||
*/
|
|
||||||
exports.setConsole = function( console )
|
|
||||||
{
|
|
||||||
_console = console;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// set the default handler
|
|
||||||
_handler = exports.handlers.log;
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,51 @@
|
||||||
|
/**
|
||||||
|
* Dismissive warning handler
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning handler that dismisses (ignores) all warnings
|
||||||
|
*
|
||||||
|
* This is useful in a production environment.
|
||||||
|
*/
|
||||||
|
function DismissiveHandler()
|
||||||
|
{
|
||||||
|
if ( !( this instanceof DismissiveHandler ) )
|
||||||
|
{
|
||||||
|
return new DismissiveHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
DismissiveHandler.prototype = {
|
||||||
|
/**
|
||||||
|
* Handle a warning
|
||||||
|
*
|
||||||
|
* @param {Warning} warning warning to handle
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
handle: function( warning )
|
||||||
|
{
|
||||||
|
// intentionally do nothing
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = DismissiveHandler;
|
||||||
|
|
|
@ -0,0 +1,64 @@
|
||||||
|
/**
|
||||||
|
* Logging warning handler
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning handler that logs all warnings to a console
|
||||||
|
*
|
||||||
|
* @param {Object} console console with a warn or log method
|
||||||
|
*/
|
||||||
|
function LogHandler( console )
|
||||||
|
{
|
||||||
|
if ( !( this instanceof LogHandler ) )
|
||||||
|
{
|
||||||
|
return new LogHandler( console );
|
||||||
|
}
|
||||||
|
|
||||||
|
this._console = console || {};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
LogHandler.prototype = {
|
||||||
|
/**
|
||||||
|
* Handle a warning
|
||||||
|
*
|
||||||
|
* Will attempt to log using console.warn(), falling back to
|
||||||
|
* console.log() if necessary and aborting entirely if neither is
|
||||||
|
* available.
|
||||||
|
*
|
||||||
|
* This is useful as a default option to bring problems to the
|
||||||
|
* developer's attention without affecting the control flow of the
|
||||||
|
* software.
|
||||||
|
*
|
||||||
|
* @param {Warning} warning warning to handle
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
handle: function( warning )
|
||||||
|
{
|
||||||
|
var dest = this._console.warn || this._console.log;
|
||||||
|
dest && dest.call( this._console,
|
||||||
|
'Warning: ' + warning.message
|
||||||
|
);
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = LogHandler;
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
/**
|
||||||
|
* Throwing warning handler
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warning handler that throws all warnings as exceptions
|
||||||
|
*/
|
||||||
|
function ThrowHandler()
|
||||||
|
{
|
||||||
|
if ( !( this instanceof ThrowHandler ) )
|
||||||
|
{
|
||||||
|
return new ThrowHandler();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ThrowHandler.prototype = {
|
||||||
|
/**
|
||||||
|
* Handle a warning
|
||||||
|
*
|
||||||
|
* Throws the error associated with the warning.
|
||||||
|
*
|
||||||
|
* This handler is useful for development and will ensure that problems
|
||||||
|
* are brought to the attention of the developer.
|
||||||
|
*
|
||||||
|
* @param {Warning} warning warning to handle
|
||||||
|
* @return {undefined}
|
||||||
|
*/
|
||||||
|
handle: function( warning )
|
||||||
|
{
|
||||||
|
throw warning.getError();
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
module.exports = ThrowHandler;
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/**
|
||||||
|
* Warning prototype
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Permits wrapping an exception as a warning
|
||||||
|
*
|
||||||
|
* Warnings are handled differently by the system, depending on the warning
|
||||||
|
* level that has been set.
|
||||||
|
*
|
||||||
|
* @param {Error} e exception (error) to wrap
|
||||||
|
*
|
||||||
|
* @return {Warning} new warning instance
|
||||||
|
*
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
function Warning( e )
|
||||||
|
{
|
||||||
|
// allow instantiation without use of 'new' keyword
|
||||||
|
if ( !( this instanceof Warning ) )
|
||||||
|
{
|
||||||
|
return new Warning( e );
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure we're wrapping an exception
|
||||||
|
if ( !( e instanceof Error ) )
|
||||||
|
{
|
||||||
|
throw TypeError( "Must provide exception to wrap" );
|
||||||
|
}
|
||||||
|
|
||||||
|
Error.prototype.constructor.call( this, e.message );
|
||||||
|
|
||||||
|
// copy over the message for convenience
|
||||||
|
this.message = e.message;
|
||||||
|
this.name = 'Warning';
|
||||||
|
this._error = e;
|
||||||
|
|
||||||
|
this.stack = e.stack &&
|
||||||
|
e.stack.replace( /^.*?\n+/,
|
||||||
|
this.name + ': ' + this.message + "\n"
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// ensures the closest compatibility...just be careful not to modify Warning's
|
||||||
|
// prototype
|
||||||
|
Warning.prototype = Error();
|
||||||
|
Warning.prototype.constructor = Warning;
|
||||||
|
Warning.prototype.name = 'Warning';
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the error wrapped by the warning
|
||||||
|
*
|
||||||
|
* @return {Error} wrapped error
|
||||||
|
*/
|
||||||
|
Warning.prototype.getError = function()
|
||||||
|
{
|
||||||
|
return this._error;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
module.exports = Warning;
|
||||||
|
|
|
@ -23,8 +23,6 @@ require( 'common' ).testCase(
|
||||||
{
|
{
|
||||||
caseSetUp: function()
|
caseSetUp: function()
|
||||||
{
|
{
|
||||||
// XXX: get rid of this disgusting mess; we're mid-refactor and all
|
|
||||||
// these dependencies should not be necessary for testing
|
|
||||||
this.Sut = this.require( 'ClassBuilder' );
|
this.Sut = this.require( 'ClassBuilder' );
|
||||||
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
|
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
|
||||||
|
|
||||||
|
@ -34,14 +32,17 @@ require( 'common' ).testCase(
|
||||||
|
|
||||||
setUp: function()
|
setUp: function()
|
||||||
{
|
{
|
||||||
|
// XXX: get rid of this disgusting mess; we're mid-refactor and all
|
||||||
|
// these dependencies should not be necessary for testing
|
||||||
this.builder = this.Sut(
|
this.builder = this.Sut(
|
||||||
this.require( '/MemberBuilder' )(
|
this.require( 'warn' ).DismissiveHandler(),
|
||||||
|
this.require( 'MemberBuilder' )(
|
||||||
this.MethodWrapperFactory( this.wrappers.wrapNew ),
|
this.MethodWrapperFactory( this.wrappers.wrapNew ),
|
||||||
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
|
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
|
||||||
this.MethodWrapperFactory( this.wrappers.wrapProxy ),
|
this.MethodWrapperFactory( this.wrappers.wrapProxy ),
|
||||||
this.getMock( 'MemberBuilderValidator' )
|
this.getMock( 'MemberBuilderValidator' )
|
||||||
),
|
),
|
||||||
this.require( '/VisibilityObjectFactoryFactory' )
|
this.require( 'VisibilityObjectFactoryFactory' )
|
||||||
.fromEnvironment()
|
.fromEnvironment()
|
||||||
)
|
)
|
||||||
},
|
},
|
||||||
|
|
|
@ -73,6 +73,7 @@ require( 'common' ).testCase(
|
||||||
{
|
{
|
||||||
// XXX: clean up this mess.
|
// XXX: clean up this mess.
|
||||||
var builder = this.require( 'ClassBuilder' )(
|
var builder = this.require( 'ClassBuilder' )(
|
||||||
|
this.require( 'warn' ).DismissiveHandler(),
|
||||||
this.require( 'MemberBuilder' )(),
|
this.require( 'MemberBuilder' )(),
|
||||||
this.require( 'VisibilityObjectFactoryFactory' )
|
this.require( 'VisibilityObjectFactoryFactory' )
|
||||||
.fromEnvironment()
|
.fromEnvironment()
|
||||||
|
|
|
@ -291,6 +291,7 @@ require( 'common' ).testCase(
|
||||||
build = this.require( 'MemberBuilder' )();
|
build = this.require( 'MemberBuilder' )();
|
||||||
|
|
||||||
var sut = this.Sut(
|
var sut = this.Sut(
|
||||||
|
this.require( 'warn' ).DismissiveHandler(),
|
||||||
build,
|
build,
|
||||||
this.require( 'VisibilityObjectFactoryFactory' )
|
this.require( 'VisibilityObjectFactoryFactory' )
|
||||||
.fromEnvironment()
|
.fromEnvironment()
|
||||||
|
|
|
@ -26,8 +26,6 @@ require( 'common' ).testCase(
|
||||||
{
|
{
|
||||||
this.fallback = this.require( 'util' ).definePropertyFallback();
|
this.fallback = this.require( 'util' ).definePropertyFallback();
|
||||||
|
|
||||||
// XXX: get rid of this disgusting mess; we're mid-refactor and all
|
|
||||||
// these dependencies should not be necessary for testing
|
|
||||||
this.ClassBuilder = this.require( 'ClassBuilder' );
|
this.ClassBuilder = this.require( 'ClassBuilder' );
|
||||||
this.MemberBuilder = this.require( 'MemberBuilder' );
|
this.MemberBuilder = this.require( 'MemberBuilder' );
|
||||||
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
|
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
|
||||||
|
@ -38,7 +36,10 @@ require( 'common' ).testCase(
|
||||||
|
|
||||||
setUp: function()
|
setUp: function()
|
||||||
{
|
{
|
||||||
|
// XXX: get rid of this disgusting mess; we're mid-refactor and all
|
||||||
|
// these dependencies should not be necessary for testing
|
||||||
this.builder = this.ClassBuilder(
|
this.builder = this.ClassBuilder(
|
||||||
|
this.require( 'warn' ).DismissiveHandler(),
|
||||||
this.MemberBuilder(
|
this.MemberBuilder(
|
||||||
this.MethodWrapperFactory( this.wrappers.wrapNew ),
|
this.MethodWrapperFactory( this.wrappers.wrapNew ),
|
||||||
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
|
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
|
||||||
|
|
|
@ -25,8 +25,6 @@ require( 'common' ).testCase(
|
||||||
{
|
{
|
||||||
caseSetUp: function()
|
caseSetUp: function()
|
||||||
{
|
{
|
||||||
// XXX: get rid of this disgusting mess; we're mid-refactor and all
|
|
||||||
// these dependencies should not be necessary for testing
|
|
||||||
this.Sut = this.require( 'ClassBuilder' );
|
this.Sut = this.require( 'ClassBuilder' );
|
||||||
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
|
this.MethodWrapperFactory = this.require( 'MethodWrapperFactory' );
|
||||||
|
|
||||||
|
@ -37,7 +35,10 @@ require( 'common' ).testCase(
|
||||||
|
|
||||||
setUp: function()
|
setUp: function()
|
||||||
{
|
{
|
||||||
|
// XXX: get rid of this disgusting mess; we're mid-refactor and all
|
||||||
|
// these dependencies should not be necessary for testing
|
||||||
this.builder = this.Sut(
|
this.builder = this.Sut(
|
||||||
|
this.require( 'warn' ).DismissiveHandler(),
|
||||||
this.require( '/MemberBuilder' )(
|
this.require( '/MemberBuilder' )(
|
||||||
this.MethodWrapperFactory( this.wrappers.wrapNew ),
|
this.MethodWrapperFactory( this.wrappers.wrapNew ),
|
||||||
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
|
this.MethodWrapperFactory( this.wrappers.wrapOverride ),
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
/**
|
||||||
|
* Tests global scope handling
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
var _global = this;
|
||||||
|
|
||||||
|
require( 'common' ).testCase(
|
||||||
|
{
|
||||||
|
caseSetUp: function()
|
||||||
|
{
|
||||||
|
this.Sut = this.require( 'util/Global' );
|
||||||
|
this.gobj = this.Sut.expose();
|
||||||
|
this.uniq = '___$$easejs$globaltest$$';
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Check common environments and ensure that the returned object is
|
||||||
|
* strictly equal to the global object for that environment. For
|
||||||
|
* environments that we do *not* know about, just check for a common
|
||||||
|
* object that must exist in ES3 and above.
|
||||||
|
*/
|
||||||
|
'Global object represents environment global object': function()
|
||||||
|
{
|
||||||
|
switch ( true )
|
||||||
|
{
|
||||||
|
// browser
|
||||||
|
case _global.window:
|
||||||
|
this.assertStrictEqual( this.gobj, _global.window );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// Node.js
|
||||||
|
case _global.root:
|
||||||
|
this.assertStrictEqual( this.gobj, _global.root );
|
||||||
|
break;
|
||||||
|
|
||||||
|
// something else; we'll just check for something that should
|
||||||
|
// exist in >=ES3
|
||||||
|
default:
|
||||||
|
this.assertStrictEqual( this.gobj.Array, Array );
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Since ease.js makes use of ECMAScript features when they are
|
||||||
|
* available, it must also find a way to gracefully degrade to support
|
||||||
|
* less fortunate environments; the ability to define alternative
|
||||||
|
* definitions is key to that.
|
||||||
|
*/
|
||||||
|
'Providing alternative will set value if name does not exist':
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
var sut = this.Sut();
|
||||||
|
|
||||||
|
var field = this.uniq,
|
||||||
|
value = { _: 'easejsOK' };
|
||||||
|
|
||||||
|
sut.provideAlt( field, function() { return value; } );
|
||||||
|
this.assertStrictEqual( sut.get( field ), value );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* It is also important that our own definitions do not pollute the
|
||||||
|
* global scope; reasons for this are not just to be polite, but also
|
||||||
|
* because other code/libraries may provide their own definitions that
|
||||||
|
* we would not want to interfere with. (Indeed, we'd also want to use
|
||||||
|
* those definitions, if they already exist before provideAlt is
|
||||||
|
* called.)
|
||||||
|
*/
|
||||||
|
'Providing alternative will not pollute the global scope': function()
|
||||||
|
{
|
||||||
|
this.Sut().provideAlt( this.uniq, function() { return {} } );
|
||||||
|
this.assertEqual( this.gobj[ this.uniq ], undefined );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Our alternatives are unneeded if the object we are providing an
|
||||||
|
* alternative for is already defined.
|
||||||
|
*/
|
||||||
|
'Providing alternative will not modify global if name exists':
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
var sut = this.Sut();
|
||||||
|
|
||||||
|
// a field that must exist in ES3+
|
||||||
|
var field = 'Array',
|
||||||
|
orig = this.gobj[ field ];
|
||||||
|
|
||||||
|
sut.provideAlt( field, function() { return {}; } );
|
||||||
|
this.assertStrictEqual( sut.get( field ), orig );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Once an alternative is defined, it shall be treated as though the
|
||||||
|
* value were defined globally; providing additional alternatives should
|
||||||
|
* therefore have no effect.
|
||||||
|
*/
|
||||||
|
'Providing alternative twice will not modify first alternative':
|
||||||
|
function()
|
||||||
|
{
|
||||||
|
var sut = this.Sut();
|
||||||
|
field = this.uniq,
|
||||||
|
expected = { _: 'easejsOK' };
|
||||||
|
|
||||||
|
// first should provide alternative, second should do nothing
|
||||||
|
sut.provideAlt( field, function() { return expected; } );
|
||||||
|
sut.provideAlt( field, function() { return 'oops'; } );
|
||||||
|
|
||||||
|
this.assertStrictEqual( sut.get( field ), expected );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
'provideAlt returns self for method chaining': function()
|
||||||
|
{
|
||||||
|
var sut = this.Sut();
|
||||||
|
|
||||||
|
this.assertStrictEqual( sut,
|
||||||
|
sut.provideAlt( 'foo', function() {} )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
/**
|
||||||
|
* Tests utility module entry point
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* N.B. Despite this saying that it tests the index (i.e. entry point), this
|
||||||
|
* is not yet the case; it will be in the future, though.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require( 'common' ).testCase(
|
||||||
|
{
|
||||||
|
caseSetUp: function()
|
||||||
|
{
|
||||||
|
this.Sut = this.require( 'util' );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
'Exposes Global prototype': function()
|
||||||
|
{
|
||||||
|
this.assertStrictEqual(
|
||||||
|
this.Sut.Global,
|
||||||
|
this.require( 'util/Global' )
|
||||||
|
);
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
|
@ -0,0 +1,43 @@
|
||||||
|
/**
|
||||||
|
* Tests symbol subset
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* N.B. Despite this saying that it tests the index (i.e. entry point), this
|
||||||
|
* is not yet the case; it will be in the future, though.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
require( 'common' ).testCase(
|
||||||
|
{
|
||||||
|
caseSetUp: function()
|
||||||
|
{
|
||||||
|
this.Sut = this.require( 'util/Symbol' );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* We don't care about the details of this; just make sure that we fail
|
||||||
|
* in an environment that seems to confuse us.
|
||||||
|
*/
|
||||||
|
'Exports a function': function()
|
||||||
|
{
|
||||||
|
this.assertOk( typeof this.Sut === 'function' );
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
|
@ -0,0 +1,76 @@
|
||||||
|
/**
|
||||||
|
* Tests pre-ES6 fallback symbol subset
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
require( 'common' ).testCase(
|
||||||
|
{
|
||||||
|
caseSetUp: function()
|
||||||
|
{
|
||||||
|
this.Sut = this.require( 'util/symbol/FallbackSymbol' );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Symbols are used to create an object fields that is accessible only
|
||||||
|
* to the holder of a reference to the symbol used to create that field.
|
||||||
|
* Since this fallback is intended to be used in environments that do
|
||||||
|
* not support symbols, the alternative is to return a random string
|
||||||
|
* that is highly unlikely to exist in practice. However, we must also
|
||||||
|
* return an object to allow for instanceof checks. See below test for
|
||||||
|
* more details.
|
||||||
|
*/
|
||||||
|
'Constructor returns an instance of Symbol': function()
|
||||||
|
{
|
||||||
|
var result = this.Sut();
|
||||||
|
this.assertOk( result instanceof this.Sut );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The generated string should be unique for each call, making it
|
||||||
|
* unlikely that its value can be guessed. Of course, this relies on the
|
||||||
|
* assumption that the runtime's PRNG is reliable and that it has not
|
||||||
|
* been maliciously rewritten.
|
||||||
|
*
|
||||||
|
* Note that we don't test the various implementation details, as that
|
||||||
|
* is intended to be opaque (see SUT source for details).
|
||||||
|
*/
|
||||||
|
'Generated string varies with each call': function()
|
||||||
|
{
|
||||||
|
var gen = {},
|
||||||
|
i = 32;
|
||||||
|
|
||||||
|
while ( i-- )
|
||||||
|
{
|
||||||
|
var result = this.Sut();
|
||||||
|
if ( gen[ result ] )
|
||||||
|
{
|
||||||
|
this.fail( result, '' );
|
||||||
|
}
|
||||||
|
|
||||||
|
gen[ result ] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// this prevents the test from being marked as incomplete
|
||||||
|
this.assertOk( 'passed' );
|
||||||
|
},
|
||||||
|
} );
|
||||||
|
|
|
@ -1,176 +0,0 @@
|
||||||
/**
|
|
||||||
* Tests core warning handlers
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of GNU ease.js.
|
|
||||||
*
|
|
||||||
* ease.js is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
try { void console } catch ( e ) { console = undefined; }
|
|
||||||
|
|
||||||
require( 'common' ).testCase(
|
|
||||||
{
|
|
||||||
caseSetUp: function()
|
|
||||||
{
|
|
||||||
// XXX: this has global state
|
|
||||||
this.Sut = this.require( 'warn' );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
setUp: function()
|
|
||||||
{
|
|
||||||
this.stubwarn = this.Sut.Warning( Error( 'gninraw' ) );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The log warning handler should log warnings to the console
|
|
||||||
*/
|
|
||||||
'`log\' warning handler logs messages to console': function()
|
|
||||||
{
|
|
||||||
var _self = this,
|
|
||||||
logged = false;
|
|
||||||
|
|
||||||
// mock console
|
|
||||||
this.Sut.setConsole( {
|
|
||||||
warn: function( message )
|
|
||||||
{
|
|
||||||
// should prefix with `Warning: '
|
|
||||||
_self.assertEqual(
|
|
||||||
( 'Warning: ' + _self.stubwarn.message ),
|
|
||||||
message
|
|
||||||
);
|
|
||||||
|
|
||||||
logged = true;
|
|
||||||
},
|
|
||||||
} );
|
|
||||||
|
|
||||||
// call handler with the warning
|
|
||||||
this.Sut.handlers.log( this.stubwarn );
|
|
||||||
|
|
||||||
this.assertOk( logged, true,
|
|
||||||
"Message should be logged to console"
|
|
||||||
);
|
|
||||||
|
|
||||||
// restore console (TODO: will not be necessary once global state is
|
|
||||||
// removed)
|
|
||||||
this.Sut.setConsole( console );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Some environments may not have a console reference, or they may not
|
|
||||||
* have console.warn. In this case, we just want to make sure we don't
|
|
||||||
* throw an error when attempting to invoke undefined, or access a
|
|
||||||
* property of undefined.
|
|
||||||
*/
|
|
||||||
'`log\' warning handler handles missing console': function()
|
|
||||||
{
|
|
||||||
var Sut = this.Sut;
|
|
||||||
|
|
||||||
// destroy it
|
|
||||||
Sut.setConsole( undefined );
|
|
||||||
|
|
||||||
// attempt to log
|
|
||||||
var _self = this;
|
|
||||||
this.assertDoesNotThrow( function()
|
|
||||||
{
|
|
||||||
Sut.handlers.log( _self.warnstub );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// restore console
|
|
||||||
Sut.setConsole( console );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Furthermore, an environment may implement console.log(), but not
|
|
||||||
* console.warn(). By default, we use warn(), so let's ensure we can
|
|
||||||
* fall back to log() if warn() is unavailable.
|
|
||||||
*/
|
|
||||||
'`log\' warning handler falls back to log if warn is missing':
|
|
||||||
function()
|
|
||||||
{
|
|
||||||
var given = '';
|
|
||||||
|
|
||||||
this.Sut.setConsole( {
|
|
||||||
log: function( message )
|
|
||||||
{
|
|
||||||
given = message;
|
|
||||||
}
|
|
||||||
} );
|
|
||||||
|
|
||||||
// attempt to log
|
|
||||||
this.Sut.handlers.log( this.stubwarn );
|
|
||||||
|
|
||||||
this.assertEqual( ( 'Warning: ' + this.stubwarn.message ), given,
|
|
||||||
"Should fall back to log() and log proper message"
|
|
||||||
);
|
|
||||||
|
|
||||||
// restore console
|
|
||||||
this.Sut.setConsole( console );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The throwError warning handler should throw the wrapped error as an
|
|
||||||
* exception
|
|
||||||
*/
|
|
||||||
'`throwError\' warning handler throws wrapped error': function()
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
this.Sut.handlers.throwError( this.stubwarn );
|
|
||||||
}
|
|
||||||
catch ( e )
|
|
||||||
{
|
|
||||||
this.assertStrictEqual( e, this.stubwarn.getError(),
|
|
||||||
"Wrapped exception should be thrown"
|
|
||||||
);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this.assertFail( "Wrapped exception should be thrown" );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The 'dismiss' error handler is a pretty basic concept: simply do
|
|
||||||
* nothing. We don't want to log, we don't want to throw anything, we
|
|
||||||
* just want to pretend nothing ever happened and move on our merry way.
|
|
||||||
* This is intended for use in production environments where such
|
|
||||||
* warnings are expected to already have been worked out and would only
|
|
||||||
* confuse/concern the user.
|
|
||||||
*/
|
|
||||||
'`dismiss\' warning handler does nothing': function()
|
|
||||||
{
|
|
||||||
var Sut = this.Sut;
|
|
||||||
|
|
||||||
// destroy the console to ensure nothing is logged
|
|
||||||
Sut.setConsole( undefined );
|
|
||||||
|
|
||||||
// no errors should occur because it should not do anything.
|
|
||||||
var _self = this;
|
|
||||||
this.assertDoesNotThrow( function()
|
|
||||||
{
|
|
||||||
Sut.handlers.dismiss( _self.warnstub );
|
|
||||||
} );
|
|
||||||
|
|
||||||
// restore console
|
|
||||||
Sut.setConsole( console );
|
|
||||||
},
|
|
||||||
} );
|
|
|
@ -1,79 +0,0 @@
|
||||||
/**
|
|
||||||
* Tests warning system implementation
|
|
||||||
*
|
|
||||||
* Copyright (C) 2014 Free Software Foundation, Inc.
|
|
||||||
*
|
|
||||||
* This file is part of GNU ease.js.
|
|
||||||
*
|
|
||||||
* ease.js is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
try { void console } catch ( e ) { console = undefined; }
|
|
||||||
|
|
||||||
require( 'common' ).testCase(
|
|
||||||
{
|
|
||||||
setUp: function()
|
|
||||||
{
|
|
||||||
// XXX: this uses global state; remove that requirement.
|
|
||||||
this.Sut = this.require( 'warn' );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The default warning handler should be the 'log' handler; this is a
|
|
||||||
* friendly compromise that will allow the developer to be warned of
|
|
||||||
* potential issues without affecting program execution.
|
|
||||||
*/
|
|
||||||
'Default warning handler is `log\'': function()
|
|
||||||
{
|
|
||||||
var called = false;
|
|
||||||
|
|
||||||
// stub it
|
|
||||||
this.Sut.setConsole( {
|
|
||||||
warn: function()
|
|
||||||
{
|
|
||||||
called = true;
|
|
||||||
},
|
|
||||||
} );
|
|
||||||
|
|
||||||
this.Sut.handle( this.Sut.Warning( Error( 'foo' ) ) );
|
|
||||||
this.assertOk( called );
|
|
||||||
|
|
||||||
// restore console (TODO: this will not be necessary once reliance
|
|
||||||
// on global state is removed)
|
|
||||||
this.Sut.setConsole( console );
|
|
||||||
},
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The warning handler can be altered at runtime; ensure we can set it
|
|
||||||
* and call it appropriately. We do not need to use one of the
|
|
||||||
* pre-defined handlers.
|
|
||||||
*/
|
|
||||||
'Can set and call arbitrary warning handler': function()
|
|
||||||
{
|
|
||||||
var given,
|
|
||||||
warning = this.Sut.Warning( Error( 'foo' ) );
|
|
||||||
|
|
||||||
// set a stub warning handler
|
|
||||||
this.Sut.setHandler( function( warn )
|
|
||||||
{
|
|
||||||
given = warn;
|
|
||||||
} );
|
|
||||||
|
|
||||||
// trigger the handler
|
|
||||||
this.Sut.handle( warning );
|
|
||||||
this.assertDeepEqual( given, warning );
|
|
||||||
},
|
|
||||||
} );
|
|
|
@ -47,6 +47,6 @@ exports.require = function( module )
|
||||||
*
|
*
|
||||||
* @return {udnefined}
|
* @return {udnefined}
|
||||||
*/
|
*/
|
||||||
exports.testCase = require( __dirname + '/inc-testcase.js' );
|
exports.testCase = require( './inc-testcase.js' );
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,57 @@
|
||||||
|
/**
|
||||||
|
* Tests dismissive warning handler
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require( 'common' ).testCase(
|
||||||
|
{
|
||||||
|
caseSetUp: function()
|
||||||
|
{
|
||||||
|
this.Sut = this.require( 'warn/DismissiveHandler' );
|
||||||
|
this.Warning = this.require( 'warn/Warning' );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
'Can be instantiated without `new` keyword': function()
|
||||||
|
{
|
||||||
|
this.assertOk( this.Sut() instanceof this.Sut );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Simply do nothing. We don't want to log, we don't want to throw
|
||||||
|
* anything, we just want to pretend nothing ever happened and move on
|
||||||
|
* our merry way. This is intended for use in production environments
|
||||||
|
* where such warnings are expected to already have been worked out and
|
||||||
|
* would only confuse/concern the user.
|
||||||
|
*
|
||||||
|
* Now, testing whether it does anything or not is difficult, since it
|
||||||
|
* could do, well, anything; that said, we are not passing it anything
|
||||||
|
* via the ctor, so assuming that it does not rely on or manipulate
|
||||||
|
* global state, we need only ensure that no exceptions are thrown.
|
||||||
|
*/
|
||||||
|
'Does nothing': function()
|
||||||
|
{
|
||||||
|
var _self = this;
|
||||||
|
this.assertDoesNotThrow( function()
|
||||||
|
{
|
||||||
|
_self.Sut().handle( _self.Warning( Error( "Ignore me!" ) ) );
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
} );
|
|
@ -0,0 +1,126 @@
|
||||||
|
/**
|
||||||
|
* Tests logging warning handler
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require( 'common' ).testCase(
|
||||||
|
{
|
||||||
|
caseSetUp: function()
|
||||||
|
{
|
||||||
|
this.Sut = this.require( 'warn/LogHandler' );
|
||||||
|
this.Warning = this.require( 'warn/Warning' );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
setUp: function()
|
||||||
|
{
|
||||||
|
this.stubwarn = this.Warning( Error( 'gninraw' ) );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
'Can be instantiated without `new` keyword': function()
|
||||||
|
{
|
||||||
|
this.assertOk( this.Sut() instanceof this.Sut );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Warnings should be logged to the provided console. By default, the
|
||||||
|
* `warn` method is used (see below tests for fallbacks).
|
||||||
|
*/
|
||||||
|
'Logs messages to console': function()
|
||||||
|
{
|
||||||
|
var _self = this,
|
||||||
|
logged = false;
|
||||||
|
|
||||||
|
// mock console
|
||||||
|
this.Sut( {
|
||||||
|
warn: function( message )
|
||||||
|
{
|
||||||
|
// should prefix with `Warning: '
|
||||||
|
_self.assertEqual(
|
||||||
|
( 'Warning: ' + _self.stubwarn.message ),
|
||||||
|
message
|
||||||
|
);
|
||||||
|
|
||||||
|
logged = true;
|
||||||
|
},
|
||||||
|
} ).handle( this.stubwarn );
|
||||||
|
|
||||||
|
this.assertOk( logged, true,
|
||||||
|
"Message should be logged to console"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Some environments may not have a console reference, or they may not
|
||||||
|
* have console.warn. In this case, we just want to make sure we don't
|
||||||
|
* throw an error when attempting to invoke undefined, or access a
|
||||||
|
* property of undefined.
|
||||||
|
*/
|
||||||
|
'Ignores missing console': function()
|
||||||
|
{
|
||||||
|
var _self = this;
|
||||||
|
this.assertDoesNotThrow( function()
|
||||||
|
{
|
||||||
|
_self.Sut( undefined ).handle( _self.warnstub );
|
||||||
|
} );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Furthermore, an environment may implement `console.log`, but not
|
||||||
|
* `console.warn`. By default, we use `warn`, so let's ensure we can
|
||||||
|
* fall back to `log` if `warn` is unavailable.
|
||||||
|
*/
|
||||||
|
'Falls back to log if warn is missing': function()
|
||||||
|
{
|
||||||
|
var given = '';
|
||||||
|
|
||||||
|
this.Sut( {
|
||||||
|
log: function( message )
|
||||||
|
{
|
||||||
|
given = message;
|
||||||
|
}
|
||||||
|
} ).handle( this.stubwarn );
|
||||||
|
|
||||||
|
this.assertEqual( ( 'Warning: ' + this.stubwarn.message ), given,
|
||||||
|
"Should fall back to log() and log proper message"
|
||||||
|
);
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If both `console.warn` and `console.log` are defined (which is very
|
||||||
|
* likely to be the case), the former should take precedence.
|
||||||
|
*/
|
||||||
|
'`warn` takes precedence over `log`': function()
|
||||||
|
{
|
||||||
|
var log = warn = false;
|
||||||
|
|
||||||
|
this.Sut( {
|
||||||
|
warn: function() { warn = true },
|
||||||
|
log: function() { log = true },
|
||||||
|
} ).handle( this.stubwarn );
|
||||||
|
|
||||||
|
this.assertOk( warn );
|
||||||
|
this.assertOk( !log );
|
||||||
|
},
|
||||||
|
} );
|
|
@ -0,0 +1,60 @@
|
||||||
|
/**
|
||||||
|
* Tests throwing warning handler
|
||||||
|
*
|
||||||
|
* Copyright (C) 2014 Free Software Foundation, Inc.
|
||||||
|
*
|
||||||
|
* This file is part of GNU ease.js.
|
||||||
|
*
|
||||||
|
* ease.js is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
require( 'common' ).testCase(
|
||||||
|
{
|
||||||
|
caseSetUp: function()
|
||||||
|
{
|
||||||
|
this.Sut = this.require( 'warn/ThrowHandler' );
|
||||||
|
this.Warning = this.require( 'warn/Warning' );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
'Can be instantiated without `new` keyword': function()
|
||||||
|
{
|
||||||
|
this.assertOk( this.Sut() instanceof this.Sut );
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The wrapped error should be thrown as an exception; this effectively
|
||||||
|
* undoes the warning wrapper.
|
||||||
|
*/
|
||||||
|
'`throwError\' warning handler throws wrapped error': function()
|
||||||
|
{
|
||||||
|
var warn = this.Warning( Error( 'gninraw' ) );
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
this.Sut().handle( warn );
|
||||||
|
}
|
||||||
|
catch ( e )
|
||||||
|
{
|
||||||
|
this.assertStrictEqual( e, warn.getError(),
|
||||||
|
"Wrapped exception should be thrown"
|
||||||
|
);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.assertFail( "Wrapped exception should be thrown" );
|
||||||
|
},
|
||||||
|
} );
|
|
@ -33,8 +33,13 @@ RMTRAIL="$PATH_TOOLS/rmtrail"
|
||||||
cat_modules=$(
|
cat_modules=$(
|
||||||
cd "$PATH_TOOLS/../" &&
|
cd "$PATH_TOOLS/../" &&
|
||||||
grep -rIo ' require(.*)' lib/ \
|
grep -rIo ' require(.*)' lib/ \
|
||||||
| sed "s/^lib\///;s/\.js://;s/require( *'\.\/\(.*\)'.*/\1/" \
|
| sed " \
|
||||||
| node tools/combine-order.js
|
s/^lib\/\(\(.\+\/\)\?[^/]\+\)\.js: /\1 \2/;
|
||||||
|
s/require( *'\(.*\)'.*/\1/;
|
||||||
|
s/[^/\]\+\/\.\.//g;
|
||||||
|
s/\( \|\/\)\.\//\1/g;
|
||||||
|
" \
|
||||||
|
| node tools/combine-order.js \
|
||||||
) || {
|
) || {
|
||||||
echo "Failed to get module list" >&2
|
echo "Failed to get module list" >&2
|
||||||
exit 3
|
exit 3
|
||||||
|
@ -122,6 +127,7 @@ for module in $cat_modules; do
|
||||||
echo "( function( module, __dirname )"
|
echo "( function( module, __dirname )"
|
||||||
echo "{"
|
echo "{"
|
||||||
echo " var exports = module.exports = {};"
|
echo " var exports = module.exports = {};"
|
||||||
|
echo " __cwd = '$( dirname "$module" )';"
|
||||||
|
|
||||||
# add the module, removing trailing commas
|
# add the module, removing trailing commas
|
||||||
cat $filename | $RMTRAIL
|
cat $filename | $RMTRAIL
|
||||||
|
@ -166,6 +172,7 @@ if [ "$INC_TEST" ]; then
|
||||||
echo "( function( module, __dirname )"
|
echo "( function( module, __dirname )"
|
||||||
echo "{"
|
echo "{"
|
||||||
echo " var exports = module.exports = {};"
|
echo " var exports = module.exports = {};"
|
||||||
|
echo " __cwd = '.';"
|
||||||
|
|
||||||
# write out current test to make debugging easier in browsers with very
|
# write out current test to make debugging easier in browsers with very
|
||||||
# little debugging support
|
# little debugging support
|
||||||
|
|
|
@ -26,7 +26,7 @@ module.common = module['test/common'] = { exports: {
|
||||||
|
|
||||||
testCase: function()
|
testCase: function()
|
||||||
{
|
{
|
||||||
return require( 'test/inc-testcase' ).apply( this, arguments );
|
return require( '/test/inc-testcase' ).apply( this, arguments );
|
||||||
}
|
}
|
||||||
} };
|
} };
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
*/
|
*/
|
||||||
var easejs = {};
|
var easejs = {};
|
||||||
|
|
||||||
( function( ns_exports )
|
( function( ns_exports, __cwd )
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* CommonJS module exports
|
* CommonJS module exports
|
||||||
|
@ -42,15 +42,26 @@ var easejs = {};
|
||||||
*/
|
*/
|
||||||
var require = function( module_id )
|
var require = function( module_id )
|
||||||
{
|
{
|
||||||
// remove the './' directory prefix (every module is currently included
|
// anything that is not an absolute require path will be prefixed
|
||||||
// via a relative path), stupidly remove ../'s and remove .js extensions
|
// with __cwd, which is set by the combined module; this allows
|
||||||
var id_clean = module_id.replace( /^\.?\/|[^/]*?\/\.\.\/|\.js$/, '' );
|
// including relative paths (but note that this also means that
|
||||||
|
// modules that perform ad-hoc conditional requires after another
|
||||||
|
// module has been processed may not work properly; we don't do
|
||||||
|
// this, though)
|
||||||
|
var id_norm = ( module_id.substr( 0, 1 ) === '/' )
|
||||||
|
? module_id
|
||||||
|
: __cwd + '/' + module_id;
|
||||||
|
|
||||||
|
// strip `../`, poorly strip `./` (for example, it would also strip
|
||||||
|
// `foo./`, but we know that this won't ever be the case with our
|
||||||
|
// files), and strip leading `/`
|
||||||
|
var id_clean = id_norm.replace( /([^\/]+\/\.\.\/|\.\/|^\/)/g, '' );
|
||||||
|
|
||||||
// attempt to retrieve the module
|
// attempt to retrieve the module
|
||||||
var mod = module[ id_clean ];
|
var mod = module[ id_clean ];
|
||||||
if ( mod === undefined )
|
if ( mod === undefined )
|
||||||
{
|
{
|
||||||
throw "[ease.js] Undefined module: " + module_id;
|
throw "[ease.js] Undefined module: " + id_clean;
|
||||||
}
|
}
|
||||||
|
|
||||||
return mod.exports;
|
return mod.exports;
|
||||||
|
@ -65,5 +76,5 @@ var easejs = {};
|
||||||
ns_exports.Interface = module['interface'].exports;
|
ns_exports.Interface = module['interface'].exports;
|
||||||
ns_exports.Trait = module['Trait'].exports;
|
ns_exports.Trait = module['Trait'].exports;
|
||||||
ns_exports.version = module['version'].exports;
|
ns_exports.version = module['version'].exports;
|
||||||
} )( easejs );
|
} )( easejs, '.' );
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue