diff --git a/lib/class.js b/lib/class.js index 9ebb157..93ba5e8 100644 --- a/lib/class.js +++ b/lib/class.js @@ -44,6 +44,23 @@ var class_meta = {}; */ var class_instance = {}; +/* + * IE contains a nasty enumeration "bug" (poor implementation) that makes + * toString unenumerable. This means that, if you do obj.toString = foo, + * toString will NOT show up in `for` or hasOwnProperty(). This is a problem. + * + * This test will determine if this poor implementation exists. + */ +var enum_bug = ( + Object.prototype.propertyIsEnumerable.call( + { toString: function() {} }, + 'toString' + ) === false + ) + ? true + : false +; + /** * This module may be invoked in order to provide a more natural looking class @@ -429,6 +446,15 @@ var extend = ( function( extending ) delete props.__name; } + // IE has problems with toString() + if ( enum_bug ) + { + if ( props.toString !== Object.prototype.toString ) + { + props.__toString = props.toString; + } + } + util.propParse( props, { each: function( name, value, keywords ) { @@ -584,15 +610,19 @@ var extend = ( function( extending ) members[ 'public' ], 'toString' ) ) ) { - this.toString = ( cname ) - ? function() - { - return '[object #<' + cname + '>]'; - } - : function() - { - return '[object #]'; - } + // use __toString if available (see enum_bug), otherwise use + // our own defaults + this.toString = members[ 'public' ].__toString + || ( ( cname ) + ? function() + { + return '[object #<' + cname + '>]'; + } + : function() + { + return '[object #]'; + } + ) ; } }; diff --git a/test/test-class-extend.js b/test/test-class-extend.js index e0f8eff..f60df03 100644 --- a/test/test-class-extend.js +++ b/test/test-class-extend.js @@ -277,7 +277,7 @@ for ( var i = 0; i < class_count; i++ ) catch ( e ) { assert.notEqual( - e.toString().match( args.length + ' given' ), + e.message.match( args.length + ' given' ), null, "Class invocation should give argument count on error" ); @@ -295,12 +295,13 @@ for ( var i = 0; i < class_count; i++ ) result = '' ; - result = Class( 'Foo', + result = Class( 'FooToStr', { toString: function() { return str; - } + }, + bla: function() {}, })().toString(); assert.equal( diff --git a/test/test-class-name.js b/test/test-class-name.js index 19fa1b9..c5f00d7 100644 --- a/test/test-class-name.js +++ b/test/test-class-name.js @@ -66,7 +66,7 @@ var common = require( './common' ), catch ( e ) { assert.notEqual( - e.toString().match( name ), + e.message.match( name ), null, "Class definition argument count error string contains class name" ); @@ -96,7 +96,7 @@ var common = require( './common' ), } catch ( e ) { - var errstr = e.toString(); + var errstr = e.message; assert.notEqual( errstr.match( name ), @@ -256,7 +256,7 @@ var common = require( './common' ), catch ( e ) { assert.notEqual( - e.toString().match( name ), + e.message.match( name ), null, "Abstract class instantiation error should contain class name" ); @@ -276,7 +276,7 @@ var common = require( './common' ), catch ( e ) { assert.notEqual( - e.toString().match( '(anonymous)' ), + e.message.match( '(anonymous)' ), null, "Abstract class instantiation error should recognize that class " + "is anonymous if no name was given" diff --git a/test/test-combine.js b/test/test-combine.js index 0c384da..cdf4574 100644 --- a/test/test-combine.js +++ b/test/test-combine.js @@ -26,7 +26,12 @@ var common = require( './common' ), assert = require( 'assert' ), Class = common.require( 'class' ), Script = process.binding( 'evals' ).Script, - sandbox = {}; + + // sandbox in which combined script will be run + sandbox = { + // stub document.write() so we don't blow up + document: { write: function() {} }, + }; var files = [ 'ease.js', 'ease-full.js' ], diff --git a/test/test-interface-extend.js b/test/test-interface-extend.js index 2e542c7..f9197c5 100644 --- a/test/test-interface-extend.js +++ b/test/test-interface-extend.js @@ -192,7 +192,7 @@ for ( var i = 0; i < base_types.length; i++ ) catch ( e ) { assert.notEqual( - e.toString().match( args.length + ' given' ), + e.message.match( args.length + ' given' ), null, "Interface invocation should give argument count on error" ); diff --git a/test/test-interface-name.js b/test/test-interface-name.js index dad582c..f41f874 100644 --- a/test/test-interface-name.js +++ b/test/test-interface-name.js @@ -67,7 +67,7 @@ var common = require( './common' ), catch ( e ) { assert.notEqual( - e.toString().match( name ), + e.message.match( name ), null, "Interface definition argument count error string contains " + "interface name" @@ -98,7 +98,7 @@ var common = require( './common' ), } catch ( e ) { - var errstr = e.toString(); + var errstr = e.message; assert.notEqual( errstr.match( name ), @@ -210,7 +210,7 @@ var common = require( './common' ), { // ensure the error string contains the interface name assert.notEqual( - e.toString().match( name ), + e.message.match( name ), null, "Error contains interface name when available (" + i + ")" ); @@ -234,7 +234,7 @@ var common = require( './common' ), catch ( e ) { assert.notEqual( - e.toString().match( name ), + e.message.match( name ), null, "Interface name is included in instantiation error message" ); diff --git a/test/test-member_builder-gettersetter.js b/test/test-member_builder-gettersetter.js index 4fe908c..a6c037d 100644 --- a/test/test-member_builder-gettersetter.js +++ b/test/test-member_builder-gettersetter.js @@ -22,6 +22,12 @@ * @package test */ +// no need to test getters/setters in browsers that do not support them +if ( !Object.defineProperty ) +{ + return; +} + var common = require( './common' ), assert = require( 'assert' ), diff --git a/test/test-member_builder-method.js b/test/test-member_builder-method.js index ab24e18..3156dd4 100644 --- a/test/test-member_builder-method.js +++ b/test/test-member_builder-method.js @@ -24,7 +24,7 @@ var common = require( './common' ), assert = require( 'assert' ), - mb_common = require( './inc-member_builder-common' ) + mb_common = require( __dirname + '/inc-member_builder-common' ) ; mb_common.funcVal = 'foobar'; diff --git a/test/test-member_builder-prop.js b/test/test-member_builder-prop.js index 57b829f..1953a36 100644 --- a/test/test-member_builder-prop.js +++ b/test/test-member_builder-prop.js @@ -24,7 +24,7 @@ var common = require( './common' ), assert = require( 'assert' ), - mb_common = require( './inc-member_builder-common' ) + mb_common = require( __dirname + '/inc-member_builder-common' ) ; mb_common.value = { bar: 'baz' }; diff --git a/tools/browser-test.html b/tools/browser-test.html index bf5146f..86eb485 100644 --- a/tools/browser-test.html +++ b/tools/browser-test.html @@ -24,7 +24,7 @@ catch ( e ) { body.style.color = 'red'; - body.innerHTML = '

' + e.toString() + '

' + + body.innerHTML += '

' + e.message + '

' + '

ease.js is not guaranteed to run properly within this ' + 'browser.

' + '

If building ease.js, remember to run `make combine` ' + diff --git a/tools/combine b/tools/combine index 49c756d..50b01b7 100755 --- a/tools/combine +++ b/tools/combine @@ -99,32 +99,42 @@ if [ "$INC_TEST" ]; then # note that not all tests are included TEST_CASES=$( find $PATH_TEST \ \( -name 'test-*.js' \ - -name 'inc-*.js' \ - ! -name 'test-combine.js' \ - ! -name 'test-index.js' \ + -o -name 'inc-*.js' \ \) \ -exec basename {} \; \ + | sort \ + | grep -v 'test-\(combine\|index\).js' \ ) # include test combine template cat "$TPL_TEST_PATH" | grep -v '^#' | $RMTRAIL echo "/** TEST CASES **/" - echo "ns_exports.runTests = function ()" + echo "ns_exports.runTests = function()" echo "{" for testcase in $TEST_CASES; do filename="$PATH_TEST/$testcase" + # generate the module name by removing path and extension, then + # prefixing it with "test/" + module="${filename%.*}" + module="test/${module##*/}" + # each module must be enclosed in a closure to emulate a module echo "/** TEST CASE: $testcase **/" - echo "( function()" + echo "( function( module, __dirname )" echo "{" + echo " var exports = module.exports = {};" + + # write out current test to make debugging easier in browsers with very + # little debugging support + echo " document.write( '$module...
' )" # add the module, removing trailing commas cat $filename | $RMTRAIL - echo "} )();" + echo "} )( module['$module'] = {}, 'test' );" done echo "};"