Skip to content

Commit

Permalink
[fix] Run the child in strict-mode if the parent also runs in strict …
Browse files Browse the repository at this point in the history
…mode
  • Loading branch information
3rd-Eden committed Mar 25, 2015
1 parent 19eeb9a commit 363a17e
Show file tree
Hide file tree
Showing 2 changed files with 67 additions and 5 deletions.
35 changes: 32 additions & 3 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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);
}

//
Expand Down
37 changes: 35 additions & 2 deletions test.js
Original file line number Diff line number Diff line change
@@ -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;
Expand Down Expand Up @@ -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();
});
});

0 comments on commit 363a17e

Please sign in to comment.