Skip to content
This repository has been archived by the owner on Apr 18, 2018. It is now read-only.

Commit

Permalink
Fixed undef:true behavior to respect function hoisting
Browse files Browse the repository at this point in the history
  • Loading branch information
valueof committed Jan 20, 2012
1 parent 0c1afa7 commit ef9a5a3
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 12 deletions.
21 changes: 15 additions & 6 deletions jshint.js
Original file line number Diff line number Diff line change
Expand Up @@ -2665,12 +2665,12 @@ loop: for (;;) {
// Operators typeof and delete do not raise runtime errors even if
// the base object of a reference is null so no need to display warning
// if we're inside of typeof or delete.

if (option.undef && typeof predefined[v] !== 'boolean') {
// Attempting to subscript a null reference will throw an
// error, even within the typeof and delete operators
if (!(anonname === 'typeof' || anonname === 'delete') ||
(nexttoken &&
(nexttoken.value === '.' || nexttoken.value === '['))) {
(nexttoken && (nexttoken.value === '.' || nexttoken.value === '['))) {

isundef(funct, "'{a}' is not defined.", token, v);
}
Expand Down Expand Up @@ -4103,14 +4103,23 @@ loop: for (;;) {
}
advance('(end)');

var isDefined = function (name, context) {
do {
if (typeof context[name] === 'string')
return true;

context = context['(context)'];
} while (context);

return false;
};

// Check queued 'x is not defined' instances to see if they're still undefined.
for (i = 0; i < JSHINT.undefs.length; i += 1) {
k = JSHINT.undefs[i].slice(0);
scope = k.shift();
a = k[2];

if (typeof scope[a] !== 'string' && typeof funct[a] !== 'string') {
warning.apply(warning, k);
if (!isDefined(k[2].value, k[0])) {
warning.apply(warning, k.slice(1));
}
}
} catch (e) {
Expand Down
7 changes: 7 additions & 0 deletions tests/helpers/fixture.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
/*jshint node:true, white:true, undef:true, maxlen:100 */

var fs = require('fs');

exports.fixture = function (name) {
return fs.readFileSync(__dirname + '/../unit/fixtures/' + name).toString();
};
8 changes: 8 additions & 0 deletions tests/unit/fixtures/undef_func.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
function main () {
function foo () {
bar();
}

function bar () {
}
}
20 changes: 14 additions & 6 deletions tests/unit/options.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@

var JSHINT = require('../../jshint.js').JSHINT,
fs = require('fs'),
TestRun = require("../helpers/testhelper").setup.testRun;
TestRun = require('../helpers/testhelper').setup.testRun,
fixture = require('../helpers/fixture').fixture;

/**
* Option `shadow` allows you to re-define variables later in code.
Expand Down Expand Up @@ -74,8 +75,8 @@ exports.latedef = function () {
.test(src, { latedef: true });
};

exports.latedefwundef = function () {
var src = fs.readFileSync(__dirname + '/fixtures/latedefundef.js', 'utf8');
exports['combination of latedef and undef'] = function () {
var src = fixture('latedefundef.js');

// Assures that when `undef` is set to true, it'll report undefined variables
// and late definitions won't be reported as `latedef` is set to false.
Expand Down Expand Up @@ -309,7 +310,7 @@ exports.expr = function () {
}
};

/** Option `undef` requires you to always define variables you use */
// Option `undef` requires you to always define variables you use.
exports.undef = function () {
var src = fs.readFileSync(__dirname + '/fixtures/undef.js', 'utf8');

Expand All @@ -331,6 +332,15 @@ exports.undef = function () {
.test(src, { undef: true });
};

// Regression test for `undef` to make sure that ...
exports['undef in a function scope'] = function () {
var src = fixture('undef_func.js');

// Make sure that the lint is clean with and without undef.
TestRun().test(src);
TestRun().test(src, { undef: true });
};

/** Option `scripturl` allows the use of javascript-type URLs */
exports.scripturl = function () {
var code = [
Expand Down Expand Up @@ -961,8 +971,6 @@ exports.scope = function () {
.addError(12, "'x' used out of scope.")
.addError(20, "'aa' used out of scope.")
.addError(27, "'bb' used out of scope.")
.addError(32, "'bb' is not defined.")
.addError(36, "'bb' is not defined.")
.addError(37, "'cc' is not defined.")
.addError(42, "'bb' is not defined.")
.test(src);
Expand Down

0 comments on commit ef9a5a3

Please sign in to comment.