diff --git a/lib/ClassBuilder.js b/lib/ClassBuilder.js index 7eadf9a..3e73c08 100644 --- a/lib/ClassBuilder.js +++ b/lib/ClassBuilder.js @@ -492,10 +492,15 @@ exports.prototype.buildMembers = function buildMembers( getset: function( name, get, set, keywords ) { - var dest = ( keywordStatic( keywords ) ) ? smethods : members; + var dest = ( keywordStatic( keywords ) ) ? smethods : members, + is_static = keywordStatic( keywords ), + instLookup = ( ( is_static ) + ? staticInstLookup + : exports.getMethodInstance + ); _self._memberBuilder.buildGetterSetter( - dest, null, name, get, set, keywords, base + dest, null, name, get, set, keywords, instLookup, class_id, base ); }, diff --git a/lib/MemberBuilder.js b/lib/MemberBuilder.js index 83df3f4..05c1b46 100644 --- a/lib/MemberBuilder.js +++ b/lib/MemberBuilder.js @@ -211,6 +211,9 @@ exports.buildProp = function( members, meta, name, value, keywords, base ) * Copies a getter/setter to the appropriate member prototype, depending on * visibility, and assigns necessary metadata from keywords * + * TODO: This should essentially mirror buildMethod with regards to overrides, + * proxies, etc. + * * @param {!__visobj} members * @param {!Object} meta metadata container * @param {string} name getter name @@ -219,6 +222,10 @@ exports.buildProp = function( members, meta, name, value, keywords, base ) * * @param {!Object.} keywords parsed keywords * + * @param {Function} instCallback function to call in order to retrieve + * object to bind 'this' keyword to + * + * @param {number} cid class id * @param {Object=} base optional base object to scan * * @return {undefined} @@ -227,7 +234,7 @@ exports.buildProp = function( members, meta, name, value, keywords, base ) * @suppress {checkTypes} */ exports.buildGetterSetter = function( - members, meta, name, get, set, keywords, base + members, meta, name, get, set, keywords, instCallback, cid, base ) { var prev_data = scanMembers( members, name, base ), @@ -241,14 +248,24 @@ exports.buildGetterSetter = function( name, {}, keywords, prev_data, prev_keywords ); - get.___$$keywords$$ = keywords; + if ( get ) + { + get = this._overrideMethod( null, get, instCallback, cid ); + + // ensure we store the keywords *after* the override, otherwise they + // will be assigned to the wrapped function (the getter) + get.___$$keywords$$ = keywords; + } Object.defineProperty( getMemberVisibility( members, keywords, name ), name, { get: get, - set: set, + set: ( set ) + ? this._overrideMethod( null, set, instCallback, cid ) + : set, + enumerable: true, configurable: false, } diff --git a/lib/MemberBuilderValidator.js b/lib/MemberBuilderValidator.js index 5b53759..963a5ae 100644 --- a/lib/MemberBuilderValidator.js +++ b/lib/MemberBuilderValidator.js @@ -349,7 +349,7 @@ exports.prototype.validateGetterSetter = function( ); } - if ( !( prev_keywords[ 'virtual' ] ) ) + if ( !( prev_keywords && prev_keywords[ 'virtual' ] ) ) { throw TypeError( "Cannot override non-virtual getter/setter '" + name + "'" diff --git a/test/test-class-gettersetter.js b/test/test-class-gettersetter.js index 87f7337..2e3f091 100644 --- a/test/test-class-gettersetter.js +++ b/test/test-class-gettersetter.js @@ -77,6 +77,11 @@ Object.defineProperty( sub_foo_def, 'override bar', { enumerable: true, } ); +// this is important since the system may freeze the object, so we must have +// declared it in advance +foo_def.bar2 = ''; + + var Foo = Class.extend( foo_def ), SubFoo = Foo.extend( sub_foo_def );