From bb3956f1b4a2820fc2c8a79723717ce629e94eb9 Mon Sep 17 00:00:00 2001 From: Mike Gerwitz Date: Thu, 2 Nov 2017 00:15:31 -0400 Subject: [PATCH] Fix trait __inst `this.__inst' within trait methods will now correctly resolve to the public visibility object of the class we're mixed into, rather than `undefined'. This behavior is consistent with the rest of the system. * lib/ClassBuilder.js (initInstance): Add `inst' to private metadata. This is the public visibility object. * lib/Trait.js (tctor): Initialize concrete trait `__inst' to aforementioned `inst' metadata value. * test/Trait/LinearizationTest.js: Add respective test. --- lib/ClassBuilder.js | 3 ++- lib/Trait.js | 3 +++ test/Trait/LinearizationTest.js | 35 +++++++++++++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/lib/ClassBuilder.js b/lib/ClassBuilder.js index 31036b7..439efc3 100644 --- a/lib/ClassBuilder.js +++ b/lib/ClassBuilder.js @@ -1451,7 +1451,8 @@ function initInstance( instance ) util.defineSecureProp( instance, _priv, {} ); // add the visibility objects to the data object for this class instance - instance[ _priv ].vis = new prot(); + instance[ _priv ].vis = new prot(); + instance[ _priv ].inst = instance; } diff --git a/lib/Trait.js b/lib/Trait.js index ddc5259..dc0758e 100644 --- a/lib/Trait.js +++ b/lib/Trait.js @@ -949,6 +949,9 @@ function tctor( tc, base, privsym ) // the intimate relationship this[ f ] = C( base, this[ privsym ].vis )[ privsym ].vis; + // TODO: this should use util.defineSecureProp + this[ f ].__inst = this[ privsym ].inst; + // rebind trait's supertype context (if any) to our own, causing us // to share state bindSuperCtx( this[ f ], this, privsym ); diff --git a/test/Trait/LinearizationTest.js b/test/Trait/LinearizationTest.js index e3d2535..0191406 100644 --- a/test/Trait/LinearizationTest.js +++ b/test/Trait/LinearizationTest.js @@ -199,5 +199,40 @@ require( 'common' ).testCase( this.assertEqual( called, 3 ); this.assertOk( calledbase ); }, + + + /** + * Once all mixins are applied, a class is generated. This class is + * then instantiated, producing some object O. `this.__inst' in each + * mixin should then be bound to the public visibility object of O. + */ + '__inst refers to mixin class object': function() + { + var _self = this, + scalled = false; + + var T = this.Sut( + { + 'virtual public foo': function() + { + _self.assertStrictEqual( sut, this.__inst ); + scalled = true; + }, + } ); + + var sut = this.Class.use( T ).extend( + { + 'override public foo': function() + { + this.__super(); + }, + } )(); + + sut.foo(); + + // sanity check (this is covered by an above test, but we need to be + // sure that it doesn't silently fail beacuse it's never called) + this.assertOk( scalled ); + }, } );