Various argument handling optimizations
Permits more aggressive v8 optimization.newmaster
parent
a52fcfa1d9
commit
c76178516e
|
@ -299,9 +299,10 @@ exports.prototype.build = function extend( _, __ )
|
||||||
// ensure we'll be permitted to instantiate abstract classes for the base
|
// ensure we'll be permitted to instantiate abstract classes for the base
|
||||||
this._extending = true;
|
this._extending = true;
|
||||||
|
|
||||||
var args = Array.prototype.slice.call( arguments ),
|
var a = arguments,
|
||||||
props = args.pop() || {},
|
an = a.length,
|
||||||
base = args.pop() || exports.ClassBase,
|
props = ( ( an > 0 ) ? a[ an - 1 ] : 0 ) || {},
|
||||||
|
base = ( ( an > 1 ) ? a[ an - 2 ] : 0 ) || exports.ClassBase,
|
||||||
prototype = this._getBase( base ),
|
prototype = this._getBase( base ),
|
||||||
cname = '',
|
cname = '',
|
||||||
autoa = false,
|
autoa = false,
|
||||||
|
@ -508,7 +509,10 @@ exports.prototype.buildMembers = function buildMembers(
|
||||||
{
|
{
|
||||||
handlers[ name ] = function()
|
handlers[ name ] = function()
|
||||||
{
|
{
|
||||||
var args = Array.prototype.slice.call( arguments );
|
var args = [],
|
||||||
|
i = arguments.length;
|
||||||
|
|
||||||
|
while ( i-- ) args[ i ] = arguments[ i ];
|
||||||
|
|
||||||
// invoke the custom handler with the original handler as
|
// invoke the custom handler with the original handler as
|
||||||
// its last argument (which the custom handler may choose
|
// its last argument (which the custom handler may choose
|
||||||
|
|
112
lib/class.js
112
lib/class.js
|
@ -64,19 +64,24 @@ var _nullf = function() { return null; }
|
||||||
module.exports = function( namedef, def )
|
module.exports = function( namedef, def )
|
||||||
{
|
{
|
||||||
var type = ( typeof namedef ),
|
var type = ( typeof namedef ),
|
||||||
result = null
|
result = null,
|
||||||
|
args = [],
|
||||||
|
i = arguments.length
|
||||||
;
|
;
|
||||||
|
|
||||||
|
// passing arguments object prohibits optimizations in v8
|
||||||
|
while ( i-- ) args[ i ] = arguments[ i ];
|
||||||
|
|
||||||
switch ( type )
|
switch ( type )
|
||||||
{
|
{
|
||||||
// anonymous class
|
// anonymous class
|
||||||
case 'object':
|
case 'object':
|
||||||
result = createAnonymousClass.apply( null, arguments );
|
result = createAnonymousClass.apply( null, args );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// named class
|
// named class
|
||||||
case 'string':
|
case 'string':
|
||||||
result = createNamedClass.apply( null, arguments );
|
result = createNamedClass.apply( null, args );
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -99,10 +104,7 @@ module.exports = function( namedef, def )
|
||||||
*
|
*
|
||||||
* @return {Function} extended class
|
* @return {Function} extended class
|
||||||
*/
|
*/
|
||||||
module.exports.extend = function( baseordfn, dfn )
|
module.exports.extend = extend;
|
||||||
{
|
|
||||||
return extend.apply( this, arguments );
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -138,11 +140,11 @@ module.exports.implement = function( interfaces )
|
||||||
*/
|
*/
|
||||||
module.exports.use = function( traits )
|
module.exports.use = function( traits )
|
||||||
{
|
{
|
||||||
|
var args = [], i = arguments.length;
|
||||||
|
while( i-- ) args[ i ] = arguments[ i ];
|
||||||
|
|
||||||
// consume traits onto an empty base
|
// consume traits onto an empty base
|
||||||
return createUse(
|
return createUse( _nullf, args );
|
||||||
_nullf,
|
|
||||||
Array.prototype.slice.call( arguments )
|
|
||||||
);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -292,7 +294,10 @@ function createStaging( cname )
|
||||||
return {
|
return {
|
||||||
extend: function()
|
extend: function()
|
||||||
{
|
{
|
||||||
var args = Array.prototype.slice.apply( arguments );
|
var args = [],
|
||||||
|
i = arguments.length;
|
||||||
|
|
||||||
|
while ( i-- ) args[ i ] = arguments[ i ];
|
||||||
|
|
||||||
// extend() takes a maximum of two arguments. If only one
|
// extend() takes a maximum of two arguments. If only one
|
||||||
// argument is provided, then it is to be the class definition.
|
// argument is provided, then it is to be the class definition.
|
||||||
|
@ -308,21 +313,24 @@ function createStaging( cname )
|
||||||
|
|
||||||
implement: function()
|
implement: function()
|
||||||
{
|
{
|
||||||
|
var args = [],
|
||||||
|
i = arguments.length;
|
||||||
|
|
||||||
|
while ( i-- ) args[ i ] = arguments[ i ];
|
||||||
|
|
||||||
// implement on empty base, providing the class name to be used once
|
// implement on empty base, providing the class name to be used once
|
||||||
// extended
|
// extended
|
||||||
return createImplement(
|
return createImplement( null, args, cname );
|
||||||
null,
|
|
||||||
Array.prototype.slice.call( arguments ),
|
|
||||||
cname
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
|
|
||||||
use: function()
|
use: function()
|
||||||
{
|
{
|
||||||
return createUse(
|
var args = [],
|
||||||
_nullf,
|
i = arguments.length;
|
||||||
Array.prototype.slice.call( arguments )
|
|
||||||
);
|
while ( i-- ) args[ i ] = arguments[ i ];
|
||||||
|
|
||||||
|
return createUse( _nullf, args );
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -349,14 +357,14 @@ function createImplement( base, ifaces, cname )
|
||||||
var partial = {
|
var partial = {
|
||||||
extend: function()
|
extend: function()
|
||||||
{
|
{
|
||||||
var args = Array.prototype.slice.call( arguments ),
|
var an = arguments.length,
|
||||||
def = args.pop(),
|
def = arguments[ an - 1 ],
|
||||||
ext_base = args.pop()
|
ext_base = ( an > 1 ) ? arguments[ an - 2 ] : null
|
||||||
;
|
;
|
||||||
|
|
||||||
// if any arguments remain, then they likely misunderstood what this
|
// if any arguments remain, then they likely misunderstood what this
|
||||||
// method does
|
// method does
|
||||||
if ( args.length > 0 )
|
if ( an > 2 )
|
||||||
{
|
{
|
||||||
throw Error(
|
throw Error(
|
||||||
"Expecting no more than two arguments for extend()"
|
"Expecting no more than two arguments for extend()"
|
||||||
|
@ -394,7 +402,12 @@ function createImplement( base, ifaces, cname )
|
||||||
// much more performant (it creates a subtype before mixing in)
|
// much more performant (it creates a subtype before mixing in)
|
||||||
use: function()
|
use: function()
|
||||||
{
|
{
|
||||||
var traits = Array.prototype.slice.call( arguments );
|
var traits = [],
|
||||||
|
i = arguments.length;
|
||||||
|
|
||||||
|
// passing arguments object prohibits optimizations in v8
|
||||||
|
while ( i-- ) traits[ i ] = arguments[ i ];
|
||||||
|
|
||||||
return createUse(
|
return createUse(
|
||||||
function() { return partial.__createBase(); },
|
function() { return partial.__createBase(); },
|
||||||
traits
|
traits
|
||||||
|
@ -468,9 +481,9 @@ function createUse( basef, traits, nonbase )
|
||||||
// given during the extend operation
|
// given during the extend operation
|
||||||
partial.extend = function()
|
partial.extend = function()
|
||||||
{
|
{
|
||||||
var args = Array.prototype.slice.call( arguments ),
|
var an = arguments.length,
|
||||||
dfn = args.pop(),
|
dfn = arguments[ an - 1 ],
|
||||||
ext_base = args.pop(),
|
ext_base = ( an > 1 ) ? arguments[ an - 2 ] : null,
|
||||||
base = basef();
|
base = basef();
|
||||||
|
|
||||||
// extend the mixed class, which ensures that all super references
|
// extend the mixed class, which ensures that all super references
|
||||||
|
@ -485,12 +498,17 @@ function createUse( basef, traits, nonbase )
|
||||||
// call simply to mix in another trait
|
// call simply to mix in another trait
|
||||||
partial.use = function()
|
partial.use = function()
|
||||||
{
|
{
|
||||||
|
var args = [],
|
||||||
|
i = arguments.length;
|
||||||
|
|
||||||
|
while ( i-- ) args[ i ] = arguments[ i ];
|
||||||
|
|
||||||
return createUse(
|
return createUse(
|
||||||
function()
|
function()
|
||||||
{
|
{
|
||||||
return partial.__createBase();
|
return partial.__createBase();
|
||||||
},
|
},
|
||||||
Array.prototype.slice.call( arguments ),
|
args,
|
||||||
nonbase
|
nonbase
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
@ -557,8 +575,14 @@ function createMixedClass( base, traits )
|
||||||
*/
|
*/
|
||||||
function extend( _, __ )
|
function extend( _, __ )
|
||||||
{
|
{
|
||||||
|
var args = [],
|
||||||
|
i = arguments.length;
|
||||||
|
|
||||||
|
// passing arguments object prohibits optimizations in v8
|
||||||
|
while ( i-- ) args[ i ] = arguments[ i ];
|
||||||
|
|
||||||
// set up the new class
|
// set up the new class
|
||||||
var new_class = class_builder.build.apply( class_builder, arguments );
|
var new_class = class_builder.build.apply( class_builder, args );
|
||||||
|
|
||||||
// set up some additional convenience props
|
// set up some additional convenience props
|
||||||
setupProps( new_class );
|
setupProps( new_class );
|
||||||
|
@ -584,10 +608,9 @@ function extend( _, __ )
|
||||||
*/
|
*/
|
||||||
var implement = function( baseobj, interfaces )
|
var implement = function( baseobj, interfaces )
|
||||||
{
|
{
|
||||||
var args = Array.prototype.slice.call( arguments ),
|
var an = arguments.length,
|
||||||
dest = {},
|
dest = {},
|
||||||
base = args.pop(),
|
base = arguments[ an - 1 ],
|
||||||
len = args.length,
|
|
||||||
arg = null,
|
arg = null,
|
||||||
|
|
||||||
implemented = [],
|
implemented = [],
|
||||||
|
@ -595,9 +618,9 @@ var implement = function( baseobj, interfaces )
|
||||||
;
|
;
|
||||||
|
|
||||||
// add each of the interfaces
|
// add each of the interfaces
|
||||||
for ( var i = 0; i < len; i++ )
|
for ( var i = 0; i < ( an - 1 ); i++ )
|
||||||
{
|
{
|
||||||
arg = args[ i ];
|
arg = arguments[ i ];
|
||||||
|
|
||||||
// copy all interface methods to the class (does not yet deep copy)
|
// copy all interface methods to the class (does not yet deep copy)
|
||||||
util.propParse( arg.prototype, {
|
util.propParse( arg.prototype, {
|
||||||
|
@ -678,10 +701,10 @@ function attachImplement( func )
|
||||||
{
|
{
|
||||||
util.defineSecureProp( func, 'implement', function()
|
util.defineSecureProp( func, 'implement', function()
|
||||||
{
|
{
|
||||||
return createImplement(
|
var args = [], i = arguments.length;
|
||||||
func,
|
while( i-- ) args[ i ] = arguments[ i ];
|
||||||
Array.prototype.slice.call( arguments )
|
|
||||||
);
|
return createImplement( func, args );
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -699,11 +722,10 @@ function attachUse( func )
|
||||||
{
|
{
|
||||||
util.defineSecureProp( func, 'use', function()
|
util.defineSecureProp( func, 'use', function()
|
||||||
{
|
{
|
||||||
return createUse(
|
var args = [], i = arguments.length;
|
||||||
function() { return func; },
|
while( i-- ) args[ i ] = arguments[ i ];
|
||||||
Array.prototype.slice.call( arguments ),
|
|
||||||
true
|
return createUse( function() { return func; }, args, true );
|
||||||
);
|
|
||||||
} );
|
} );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,7 @@ var Class = require( __dirname + '/class' );
|
||||||
*/
|
*/
|
||||||
module.exports = exports = function()
|
module.exports = exports = function()
|
||||||
{
|
{
|
||||||
markAbstract( arguments );
|
markAbstract( arguments[ arguments.length - 1 ] );
|
||||||
|
|
||||||
// forward everything to Class
|
// forward everything to Class
|
||||||
var result = Class.apply( this, arguments );
|
var result = Class.apply( this, arguments );
|
||||||
|
@ -56,7 +56,7 @@ module.exports = exports = function()
|
||||||
*/
|
*/
|
||||||
exports.extend = function()
|
exports.extend = function()
|
||||||
{
|
{
|
||||||
markAbstract( arguments );
|
markAbstract( arguments[ arguments.length - 1 ] );
|
||||||
return Class.extend.apply( this, arguments );
|
return Class.extend.apply( this, arguments );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -92,18 +92,12 @@ exports.implement = function()
|
||||||
/**
|
/**
|
||||||
* Causes a definition to be flagged as abstract
|
* Causes a definition to be flagged as abstract
|
||||||
*
|
*
|
||||||
* This function assumes the last argument to be the definition, which is the
|
* @param {*} dfn suspected definition object
|
||||||
* common case, and modifies the object referenced by that argument.
|
|
||||||
*
|
|
||||||
* @param {Arguments} args arguments to parse
|
|
||||||
*
|
*
|
||||||
* @return {undefined}
|
* @return {undefined}
|
||||||
*/
|
*/
|
||||||
function markAbstract( args )
|
function markAbstract( dfn )
|
||||||
{
|
{
|
||||||
// the last argument _should_ be the definition
|
|
||||||
var dfn = args[ args.length - 1 ];
|
|
||||||
|
|
||||||
if ( typeof dfn === 'object' )
|
if ( typeof dfn === 'object' )
|
||||||
{
|
{
|
||||||
// mark as abstract
|
// mark as abstract
|
||||||
|
@ -141,7 +135,7 @@ function abstractOverride( obj )
|
||||||
// wrap extend, applying the abstract flag
|
// wrap extend, applying the abstract flag
|
||||||
obj.extend = function()
|
obj.extend = function()
|
||||||
{
|
{
|
||||||
markAbstract( arguments );
|
markAbstract( arguments[ arguments.length - 1 ] );
|
||||||
return extend.apply( this, arguments );
|
return extend.apply( this, arguments );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ var Class = require( __dirname + '/class' );
|
||||||
*/
|
*/
|
||||||
exports = module.exports = function()
|
exports = module.exports = function()
|
||||||
{
|
{
|
||||||
markFinal( arguments );
|
markFinal( arguments[ arguments.length - 1 ] );
|
||||||
|
|
||||||
// forward everything to Class
|
// forward everything to Class
|
||||||
var result = Class.apply( this, arguments );
|
var result = Class.apply( this, arguments );
|
||||||
|
@ -50,7 +50,7 @@ exports = module.exports = function()
|
||||||
*/
|
*/
|
||||||
exports.extend = function()
|
exports.extend = function()
|
||||||
{
|
{
|
||||||
markFinal( arguments );
|
markFinal( arguments[ arguments.length - 1 ] );
|
||||||
return Class.extend.apply( this, arguments );
|
return Class.extend.apply( this, arguments );
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -58,18 +58,12 @@ exports.extend = function()
|
||||||
/**
|
/**
|
||||||
* Causes a definition to be flagged as final
|
* Causes a definition to be flagged as final
|
||||||
*
|
*
|
||||||
* This function assumes the last argument to be the definition, which is the
|
* @param {!Arguments} dfn suspected definition object
|
||||||
* common case, and modifies the object referenced by that argument.
|
|
||||||
*
|
|
||||||
* @param {!Arguments} args arguments to parse
|
|
||||||
*
|
*
|
||||||
* @return {undefined}
|
* @return {undefined}
|
||||||
*/
|
*/
|
||||||
function markFinal( args )
|
function markFinal( dfn )
|
||||||
{
|
{
|
||||||
// the last argument _should_ be the definition
|
|
||||||
var dfn = args[ args.length - 1 ];
|
|
||||||
|
|
||||||
if ( typeof dfn === 'object' )
|
if ( typeof dfn === 'object' )
|
||||||
{
|
{
|
||||||
// mark as abstract
|
// mark as abstract
|
||||||
|
@ -92,7 +86,7 @@ function finalOverride( obj )
|
||||||
// wrap extend, applying the abstract flag
|
// wrap extend, applying the abstract flag
|
||||||
obj.extend = function()
|
obj.extend = function()
|
||||||
{
|
{
|
||||||
markFinal( arguments );
|
markFinal( arguments[ arguments.length - 1 ] );
|
||||||
return extend.apply( this, arguments );
|
return extend.apply( this, arguments );
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -184,9 +184,10 @@ var extend = ( function( extending )
|
||||||
// ensure we'll be permitted to instantiate interfaces for the base
|
// ensure we'll be permitted to instantiate interfaces for the base
|
||||||
extending = true;
|
extending = true;
|
||||||
|
|
||||||
var args = Array.prototype.slice.call( arguments ),
|
var a = arguments,
|
||||||
props = args.pop() || {},
|
an = a.length,
|
||||||
base = args.pop() || Interface,
|
props = ( ( an > 0 ) ? a[ an - 1 ] : 0 ) || {},
|
||||||
|
base = ( ( an > 1 ) ? a[ an - 2 ] : 0 ) || Interface,
|
||||||
prototype = new base(),
|
prototype = new base(),
|
||||||
iname = '',
|
iname = '',
|
||||||
|
|
||||||
|
|
|
@ -399,7 +399,10 @@ function verifyAbstractNames( name, params )
|
||||||
*/
|
*/
|
||||||
exports.createAbstractMethod = function( def )
|
exports.createAbstractMethod = function( def )
|
||||||
{
|
{
|
||||||
var definition = Array.prototype.slice.call( arguments );
|
var dfn = [],
|
||||||
|
i = arguments.length;
|
||||||
|
|
||||||
|
while ( i-- ) dfn[ i ] = arguments[ i ];
|
||||||
|
|
||||||
var method = function()
|
var method = function()
|
||||||
{
|
{
|
||||||
|
@ -407,7 +410,7 @@ exports.createAbstractMethod = function( def )
|
||||||
};
|
};
|
||||||
|
|
||||||
exports.defineSecureProp( method, 'abstractFlag', true );
|
exports.defineSecureProp( method, 'abstractFlag', true );
|
||||||
exports.defineSecureProp( method, 'definition', definition );
|
exports.defineSecureProp( method, 'definition', dfn );
|
||||||
exports.defineSecureProp( method, '__length', arguments.length );
|
exports.defineSecureProp( method, '__length', arguments.length );
|
||||||
|
|
||||||
return method;
|
return method;
|
||||||
|
|
Loading…
Reference in New Issue