diff --git a/index.js b/index.js index 27ca345..46fa53a 100644 --- a/index.js +++ b/index.js @@ -58,6 +58,37 @@ function mixin(obj) { return obj; } +/** + * Detect if a given parent is constructed in strict mode so we can force the + * child in to the same mode. It detects the strict mode by accessing properties + * on the function that are forbidden in strict mode: + * + * - `caller` + * - `callee` + * - `arguments` + * + * Forcing the a thrown TypeError. + * + * @param {Function} parent Parent constructor + * @returns {Function} The child constructor + * @api private + */ +function mode(parent) { + try { + var e = parent.caller || parent.arguments || parent.callee; + + return function child() { + return parent.apply(this, arguments); + }; + } catch(e) {} + + return function child() { + 'use strict'; + + return parent.apply(this, arguments); + }; +} + // // Helper function to correctly set up the prototype chain, for subclasses. // Similar to `goog.inherits`, but uses a hash of prototype properties and @@ -75,9 +106,7 @@ module.exports = function extend(protoProps, staticProps) { if (protoProps && has.call(protoProps, 'constructor')) { child = protoProps.constructor; } else { - child = function () { - return parent.apply(this, arguments); - }; + child = mode(parent); } // diff --git a/test.js b/test.js index 5a1cfcf..9a8cb3d 100644 --- a/test.js +++ b/test.js @@ -1,6 +1,5 @@ describe('extendible', function () { - 'use strict'; - + // 'use strict'; // Disabled for strict-mode vs global mode tests; var assume = require('assume') , extend = require('./') , Foo; @@ -80,4 +79,38 @@ describe('extendible', function () { assume(baz.my).equals('name is baz'); assume(bob.my).equals('name is bob'); }); + + it('runs in strict mode if the parent runs in strict mode', function (next) { + next = assume.plan(2, next); + + var Baz = function () { + 'use strict'; + + assume(this).equals(undefined); + }; + + Baz.extend = extend; + + var Bar = Baz.extend() + , bar = Bar() + , baz = Baz(); + + next(); + }); + + it('runs in does not run in strict mode if the parent isnt', function (next) { + next = assume.plan(2, next); + + var Baz = function () { + assume(this).equals(global); + }; + + Baz.extend = extend; + + var Bar = Baz.extend() + , bar = Bar() + , baz = Baz(); + + next(); + }); });