From 84e80b8154dd906b327b3df0c43c0bbf1211a1f6 Mon Sep 17 00:00:00 2001
From: robocoder <anthon.pang@gmail.com>
Date: Wed, 8 Jun 2011 02:06:32 +0000
Subject: [PATCH] fix piwik.js unit tests (disable jslint option.type and other
 nitpickiness)

git-svn-id: http://dev.piwik.org/svn/trunk@4896 59fd770c-687e-43c8-a1e3-f5a4ff64c105
---
 js/piwik.js                       |   13 +-
 piwik.js                          |    2 +-
 tests/javascript/jslint/jslint.js | 1411 +++++++++++++++--------------
 3 files changed, 734 insertions(+), 692 deletions(-)

diff --git a/js/piwik.js b/js/piwik.js
index 78ad563e51..9b1445ed2d 100644
--- a/js/piwik.js
+++ b/js/piwik.js
@@ -28,7 +28,7 @@
  * JSON - public domain reference implementation by Douglas Crockford
  * @link http://www.JSON.org/json2.js
  ************************************************************/
-/*jslint evil: true, strict: true, regexp: false */
+/*jslint evil: true, strict: true, regexp: false, type: true */
 /*global JSON2 */
 /*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON2, "\\", apply,
     call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
@@ -368,7 +368,10 @@ if (!this.JSON2) {
  ************************************************************/
 
 /*jslint browser:true, plusplus:false, onevar:false, strict:true, evil:true */
-/*global window unescape ActiveXObject _paq:true */
+/*global window */
+/*global unescape */
+/*global ActiveXObject */
+/*global _paq:true */
 /*members encodeURIComponent, decodeURIComponent,
 	shift, unshift,
 	addEventListener, attachEvent, removeEventListener, detachEvent,
@@ -387,7 +390,7 @@ if (!this.JSON2) {
 	pdf, qt, realp, wma, dir, fla, java, gears, ag,
 	hook, getHook, getVisitorId, getVisitorInfo, setTrackerUrl, setSiteId,
 	getAttributionInfo, getAttributionCampaignName, getAttributionCampaignKeyword, 
-	getAttributionReferrerTimestamp, getAttributionReferrerUrl
+	getAttributionReferrerTimestamp, getAttributionReferrerUrl,
 	setCustomData, getCustomData,
 	setCustomVariable, getCustomVariable, deleteCustomVariable,
 	setDownloadExtensions, addDownloadExtensions,
@@ -397,7 +400,7 @@ if (!this.JSON2) {
 	setCampaignNameKey, setCampaignKeywordKey,
 	discardHashTag,
 	setCookieNamePrefix, setCookieDomain, setCookiePath, setVisitorIdCookie,
-	setVisitorCookieTimeout, setSessionCookieTimeout, setReferralCookieTimeout
+	setVisitorCookieTimeout, setSessionCookieTimeout, setReferralCookieTimeout,
 	setConversionAttributionFirstReferrer,
 	doNotTrack, setDoNotTrack,
 	addListener, enableLinkTracking, setLinkTrackingTimer,
@@ -691,7 +694,7 @@ var
 
 			documentAlias.cookie = cookieName + '=' + encodeWrapper(value) +
 				(msToExpire ? ';expires=' + expiryDate.toGMTString() : '') +
-				';path=' + (path ? path : '/') +
+				';path=' + (path || '/') +
 				(domain ? ';domain=' + domain : '') +
 				(secure ? ';secure' : '');
 		}
diff --git a/piwik.js b/piwik.js
index 3373c381ff..b8b51aa1dd 100644
--- a/piwik.js
+++ b/piwik.js
@@ -12,7 +12,7 @@ function a(f){i.lastIndex=0;return i.test(f)?'"'+f.replace(i,function(m){var n=k
 return t}}if(typeof JSON2.stringify!=="function"){JSON2.stringify=function(o,m,n){var f;j="";b="";if(typeof n==="number"){for(f=0;f<n;f+=1){b+=" "}}else{if(typeof n==="string"){b=n}}h=m;if(m&&typeof m!=="function"&&(typeof m!=="object"||typeof m.length!=="number")){throw new Error("JSON.stringify")}return g("",{"":o})}}if(typeof JSON2.parse!=="function"){JSON2.parse=function(o,f){var n;function m(s,r){var q,p,t=s[r];if(t&&typeof t==="object"){for(q in t){if(Object.prototype.hasOwnProperty.call(t,q)){p=m(t,q);if(p!==undefined){t[q]=p}else{delete t[q]}}}}return f.call(s,r,t)}o=String(o);c.lastIndex=0;if(c.test(o)){o=o.replace(c,function(p){return"\\u"+("0000"+p.charCodeAt(0).toString(16)).slice(-4)})}if((new RegExp("^[\\],:{}\\s]*$")).test(o.replace(new RegExp('\\\\(?:["\\\\/bfnrt]|u[0-9a-fA-F]{4})',"g"),"@").replace(new RegExp('"[^"\\\\\n\r]*"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?',"g"),"]").replace(new RegExp("(?:^|:|,)(?:\\s*\\[)+","g"),""))){n=eval("("+o+")");
 return typeof f==="function"?m({"":n},""):n}throw new SyntaxError("JSON.parse")}}}());var _paq=_paq||[],Piwik=Piwik||(function(){var m,w={},d=document,j=navigator,v=screen,H=window,h=false,C=[],e=H.encodeURIComponent,I=H.decodeURIComponent,G,D;function b(i){return typeof i!=="undefined"}function a(i){return typeof i==="function"}function n(i){return typeof i==="object"}function q(i){return typeof i==="string"||i instanceof String}function z(J){var i=J.shift();if(q(i)){G[i].apply(G,J)}else{i.apply(G,J)}}function t(L,K,J,i){if(L.addEventListener){L.addEventListener(K,J,i);return true}if(L.attachEvent){return L.attachEvent("on"+K,J)}L["on"+K]=J}function g(K,N){var J="",M,L;for(M in w){if(Object.prototype.hasOwnProperty.call(w,M)){L=w[M][K];if(a(L)){J+=L(N)}}}return J}function B(){var i;g("unload");if(m){do{i=new Date()}while(i.getTime()<m)}}function k(){var J;if(!h){h=true;g("load");for(J=0;J<C.length;J++){C[J]()}}return true}function x(){var J;if(d.addEventListener){t(d,"DOMContentLoaded",function i(){d.removeEventListener("DOMContentLoaded",i,false);
 k()})}else{if(d.attachEvent){d.attachEvent("onreadystatechange",function i(){if(d.readyState==="complete"){d.detachEvent("onreadystatechange",i);k()}});if(d.documentElement.doScroll&&H===H.top){(function i(){if(!h){try{d.documentElement.doScroll("left")}catch(K){setTimeout(i,0);return}k()}}())}}}if((new RegExp("WebKit")).test(j.userAgent)){J=setInterval(function(){if(h||/loaded|complete/.test(d.readyState)){clearInterval(J);k()}},10)}t(H,"load",k,false)}function f(){var i="";try{i=H.top.document.referrer}catch(K){if(H.parent){try{i=H.parent.document.referrer}catch(J){i=""}}}if(i===""){i=d.referrer}return i}function A(i){var K=new RegExp("^([a-z]+):"),J=K.exec(i);return J?J[1]:null}function y(i){var K=new RegExp("^(?:(?:https?|ftp):)/*(?:[^@]+@)?([^:/#]+)"),J=K.exec(i);return J?J[1]:i}function p(K,J){var N=new RegExp("^(?:https?|ftp)(?::/*(?:[^?]+)[?])([^#]+)"),M=N.exec(K),L=new RegExp("(?:^|&)"+J+"=([^&]*)"),i=M?L.exec(M[1]):0;return i?I(i[1]):""}function s(O,L,K,N,J,M){var i;if(K){i=new Date();
-i.setTime(i.getTime()+K)}d.cookie=O+"="+e(L)+(K?";expires="+i.toGMTString():"")+";path="+(N?N:"/")+(J?";domain="+J:"")+(M?";secure":"")}function F(K){var i=new RegExp("(^|;)[ ]*"+K+"=([^;]*)"),J=i.exec(d.cookie);return J?I(J[2]):0}function r(i){return unescape(e(i))}function u(Z){var L=function(W,i){return(W<<i)|(W>>>(32-i))},aa=function(ag){var af="",ae,W;for(ae=7;ae>=0;ae--){W=(ag>>>(ae*4))&15;af+=W.toString(16)}return af},O,ac,ab,K=[],S=1732584193,Q=4023233417,P=2562383102,N=271733878,M=3285377520,Y,X,V,U,T,ad,J,R=[];Z=r(Z);J=Z.length;for(ac=0;ac<J-3;ac+=4){ab=Z.charCodeAt(ac)<<24|Z.charCodeAt(ac+1)<<16|Z.charCodeAt(ac+2)<<8|Z.charCodeAt(ac+3);R.push(ab)}switch(J&3){case 0:ac=2147483648;break;case 1:ac=Z.charCodeAt(J-1)<<24|8388608;break;case 2:ac=Z.charCodeAt(J-2)<<24|Z.charCodeAt(J-1)<<16|32768;break;case 3:ac=Z.charCodeAt(J-3)<<24|Z.charCodeAt(J-2)<<16|Z.charCodeAt(J-1)<<8|128;break}R.push(ac);while((R.length&15)!==14){R.push(0)}R.push(J>>>29);R.push((J<<3)&4294967295);for(O=0;O<R.length;
+i.setTime(i.getTime()+K)}d.cookie=O+"="+e(L)+(K?";expires="+i.toGMTString():"")+";path="+(N||"/")+(J?";domain="+J:"")+(M?";secure":"")}function F(K){var i=new RegExp("(^|;)[ ]*"+K+"=([^;]*)"),J=i.exec(d.cookie);return J?I(J[2]):0}function r(i){return unescape(e(i))}function u(Z){var L=function(W,i){return(W<<i)|(W>>>(32-i))},aa=function(ag){var af="",ae,W;for(ae=7;ae>=0;ae--){W=(ag>>>(ae*4))&15;af+=W.toString(16)}return af},O,ac,ab,K=[],S=1732584193,Q=4023233417,P=2562383102,N=271733878,M=3285377520,Y,X,V,U,T,ad,J,R=[];Z=r(Z);J=Z.length;for(ac=0;ac<J-3;ac+=4){ab=Z.charCodeAt(ac)<<24|Z.charCodeAt(ac+1)<<16|Z.charCodeAt(ac+2)<<8|Z.charCodeAt(ac+3);R.push(ab)}switch(J&3){case 0:ac=2147483648;break;case 1:ac=Z.charCodeAt(J-1)<<24|8388608;break;case 2:ac=Z.charCodeAt(J-2)<<24|Z.charCodeAt(J-1)<<16|32768;break;case 3:ac=Z.charCodeAt(J-3)<<24|Z.charCodeAt(J-2)<<16|Z.charCodeAt(J-1)<<8|128;break}R.push(ac);while((R.length&15)!==14){R.push(0)}R.push(J>>>29);R.push((J<<3)&4294967295);for(O=0;O<R.length;
 O+=16){for(ac=0;ac<16;ac++){K[ac]=R[O+ac]}for(ac=16;ac<=79;ac++){K[ac]=L(K[ac-3]^K[ac-8]^K[ac-14]^K[ac-16],1)}Y=S;X=Q;V=P;U=N;T=M;for(ac=0;ac<=19;ac++){ad=(L(Y,5)+((X&V)|(~X&U))+T+K[ac]+1518500249)&4294967295;T=U;U=V;V=L(X,30);X=Y;Y=ad}for(ac=20;ac<=39;ac++){ad=(L(Y,5)+(X^V^U)+T+K[ac]+1859775393)&4294967295;T=U;U=V;V=L(X,30);X=Y;Y=ad}for(ac=40;ac<=59;ac++){ad=(L(Y,5)+((X&V)|(X&U)|(V&U))+T+K[ac]+2400959708)&4294967295;T=U;U=V;V=L(X,30);X=Y;Y=ad}for(ac=60;ac<=79;ac++){ad=(L(Y,5)+(X^V^U)+T+K[ac]+3395469782)&4294967295;T=U;U=V;V=L(X,30);X=Y;Y=ad}S=(S+Y)&4294967295;Q=(Q+X)&4294967295;P=(P+V)&4294967295;N=(N+U)&4294967295;M=(M+T)&4294967295}ad=aa(S)+aa(Q)+aa(P)+aa(N)+aa(M);return ad.toLowerCase()}function o(K,i,J){if(K==="translate.googleusercontent.com"){if(J===""){J=i}i=p(i,"u");K=y(i)}else{if(K==="cc.bingj.com"||K==="webcache.googleusercontent.com"||K.slice(0,5)==="74.6."){i=d.links[0].href;K=y(i)}}return[K,i,J]}function l(J){var i=J.length;if(J.charAt(--i)==="."){J=J.slice(0,i)}if(J.slice(0,2)==="*."){J=J.slice(1)
 }return J}function E(ab,ay){var M=o(d.domain,H.location.href,f()),aQ=l(M[0]),a3=M[1],aE=M[2],aC="GET",L=ab||"",aU=ay||"",ao,ag=d.title,ai="7z|aac|ar[cj]|as[fx]|avi|bin|csv|deb|dmg|doc|exe|flv|gif|gz|gzip|hqx|jar|jpe?g|js|mp(2|3|4|e?g)|mov(ie)?|ms[ip]|od[bfgpst]|og[gv]|pdf|phps|png|ppt|qtm?|ra[mr]?|rpm|sea|sit|tar|t?bz2?|tgz|torrent|txt|wav|wm[av]|wpd||xls|xml|z|zip",aA=[aQ],P=[],at=[],aa=[],az=500,Q,ac,R,S,ak=["pk_campaign","piwik_campaign","utm_campaign","utm_source","utm_medium"],af=["pk_kwd","piwik_kwd","utm_term"],a1="_pk_",U,a2,aW,an,Y=63072000000,Z=1800000,ap=15768000000,X=d.location.protocol==="https",O=false,au={},aX=100,ae=5,aK={},aV={},aH=false,aF=false,aD,av,V,aj=u,aG,am;function aY(a6){var a7;if(R){a7=new RegExp("#.*");return a6.replace(a7,"")}return a6}function aP(a8,a6){var a9=A(a6),a7;if(a9){return a6}if(a6.slice(0,1)==="/"){return A(a8)+"://"+y(a8)+a6}a8=aY(a8);if((a7=a8.indexOf("?"))>=0){a8=a8.slice(0,a7)}if((a7=a8.lastIndexOf("/"))!==a8.length-1){a8=a8.slice(0,a7+1)}return a8+a6
 }function aB(a9){var a7,a6,a8;for(a7=0;a7<aA.length;a7++){a6=l(aA[a7].toLowerCase());if(a9===a6){return true}if(a6.slice(0,1)==="."){if(a9===a6.slice(1)){return true}a8=a9.length-a6.length;if((a8>0)&&(a9.slice(a8)===a6)){return true}}}return false}function a5(a6){var a7=new Image(1,1);a7.onLoad=function(){};a7.src=L+(L.indexOf("?")<0?"?":"&")+a6}function aM(a6){try{var a8=H.XDomainRequest?new H.XDomainRequest():H.XMLHttpRequest?new H.XMLHttpRequest():H.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):null;a8.open("POST",L,true);a8.onreadystatechange=function(){if(this.readyState===4&&this.status!==200){a5(a6)}};a8.setRequestHeader("Content-Type","application/x-www-form-urlencoded; charset=UTF-8");a8.send(a6)}catch(a7){a5(a6)}}function al(a8,a7){var a6=new Date();if(!aW){if(aC==="POST"){aM(a8)}else{a5(a8)}m=a6.getTime()+a7}}function aL(a6){return a1+a6+"."+aU+"."+aG}function N(){var a6=aL("testcookie");if(!b(j.cookieEnabled)){s(a6,"1");return F(a6)==="1"?"1":"0"}return j.cookieEnabled?"1":"0"
diff --git a/tests/javascript/jslint/jslint.js b/tests/javascript/jslint/jslint.js
index 09415e8218..5eaa8b2f67 100644
--- a/tests/javascript/jslint/jslint.js
+++ b/tests/javascript/jslint/jslint.js
@@ -1,5 +1,5 @@
 // jslint.js
-// 2011-05-10
+// 2011-06-07
 
 // Copyright (c) 2002 Douglas Crockford  (www.JSLint.com)
 
@@ -23,6 +23,7 @@
 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 // SOFTWARE.
 
+// WARNING: JSLint will hurt your feelings.
 
 // JSLINT is a global function. It takes two parameters.
 
@@ -111,6 +112,9 @@
 //                 unused: [
 //                     STRING
 //                 ],
+//                 undef: [
+//                     STRING
+//                 ],
 //                 global: [
 //                     STRING
 //                 ],
@@ -125,18 +129,6 @@
 //         member: {
 //             STRING: NUMBER
 //         },
-//         unuseds: [
-//             {
-//                 name: STRING,
-//                 line: NUMBER
-//             }
-//         ],
-//         implieds: [
-//             {
-//                 name: STRING,
-//                 line: NUMBER
-//             }
-//         ],
 //         urls: [
 //             STRING
 //         ],
@@ -190,6 +182,7 @@
 //     undef      true, if variables should be declared before used
 //     unparam    true, if unused parameters should be tolerated
 //     safe       true, if use of some browser features should be restricted
+//     type       true, if types can be used inconsistently
 //     windows    true, if MS Windows-specific globals should be predefined
 //     strict     true, require the 'use strict'; pragma
 //     sub        true, if all forms of subscript notation are tolerated
@@ -199,7 +192,7 @@
 // For example:
 
 /*jslint
-    evil: true, nomen: false, onevar: false, regexp: false, strict: true
+    evil: true, nomen: false, regexp: false, strict: true
 */
 
 // The properties directive declares an exclusive list of property names.
@@ -208,12 +201,12 @@
 
 // For example:
 
-/*properties "\b", "\t", "\n", "\f", "\r", "!=", "!==", "\"", "%",
-    "&", "'", "(begin)", "(breakage)", "(complexity)", "(context)", "(error)",
-    "(global)", "(identifier)", "(line)", "(loopage)", "(name)", "(onevar)",
-    "(params)", "(scope)", "(statement)", "(token)", "(verb)", ")", "*",
-    "+", "-", "/", ";", "<", "<<", "<=", "==", "===", ">",
-    ">=", ">>", ">>>", ADSAFE, ActiveXObject, Array,
+/*properties '\b', '\t', '\n', '\f', '\r', '!=', '!==', '"', '%',
+    '&', '\'', '(begin)', '(breakage)', '(complexity)', '(context)',
+    '(error)', '(identifier)', '(line)', '(loopage)', '(name)', '(onevar)',
+    '(params)', '(scope)', '(statement)', '(token)', '(verb)', ')', '*',
+    '+', '-', '/', ';', '<', '<<', '<=', '==', '===', '>',
+    '>=', '>>', '>>>', ADSAFE, ActiveXObject, Array,
     Boolean, Buffer, COM, CScript, Canvas, CustomAnimation, Date, Debug, E,
     Enumerator, Error, EvalError, FadeAnimation, Flash, FormField, Frame,
     Function, HotKey, Image, JSON, LN10, LN2, LOG10E, LOG2E, MAX_VALUE,
@@ -222,9 +215,9 @@
     ReferenceError, RegExp, ResizeAnimation, RotateAnimation, SQRT1_2,
     SQRT2, ScrollBar, Storage, String, Style, SyntaxError, System, Text,
     TextArea, Timer, TypeError, URIError, URL, VBArray, WScript, Web,
-    Window, XMLDOM, XMLHttpRequest, "\\", "^", __dirname, __filename, a,
-    a_function, a_label, a_not_allowed, a_not_defined, a_scope, abbr,
-    acronym, activeborder, activecaption, address, adsafe, adsafe_a,
+    Window, XMLDOM, XMLHttpRequest, '\\', '^', __dirname, __filename, a,
+    a_label, a_not_allowed, a_not_defined, a_scope, abbr, acronym,
+    activeborder, activecaption, address, adsafe, adsafe_a,
     adsafe_autocomplete, adsafe_bad_id, adsafe_div, adsafe_fragment,
     adsafe_go, adsafe_html, adsafe_id, adsafe_id_go, adsafe_lib,
     adsafe_lib_second, adsafe_missing_id, adsafe_name_a, adsafe_placement,
@@ -234,29 +227,29 @@
     aquamarine, area, arguments, arity, article, aside, assign,
     assign_exception, assignment_function_expression, at, attribute_case_a,
     audio, autocomplete, avoid_a, azure, b, background,
-    "background-attachment", "background-color", "background-image",
-    "background-position", "background-repeat", bad_assignment, bad_color_a,
+    'background-attachment', 'background-color', 'background-image',
+    'background-position', 'background-repeat', bad_assignment, bad_color_a,
     bad_constructor, bad_entity, bad_html, bad_id_a, bad_in_a,
     bad_invocation, bad_name_a, bad_new, bad_number, bad_operand, bad_type,
     bad_url, bad_wrap, base, bdo, beep, beige, big, bisque, bitwise, black,
     blanchedalmond, block, blockquote, blue, blueviolet, body, border,
-    "border-bottom", "border-bottom-color", "border-bottom-style",
-    "border-bottom-width", "border-collapse", "border-color", "border-left",
-    "border-left-color", "border-left-style", "border-left-width",
-    "border-right", "border-right-color", "border-right-style",
-    "border-right-width", "border-spacing", "border-style", "border-top",
-    "border-top-color", "border-top-style", "border-top-width",
-    "border-width", bottom, br, braille, brown, browser, burlywood, button,
+    'border-bottom', 'border-bottom-color', 'border-bottom-style',
+    'border-bottom-width', 'border-collapse', 'border-color', 'border-left',
+    'border-left-color', 'border-left-style', 'border-left-width',
+    'border-right', 'border-right-color', 'border-right-style',
+    'border-right-width', 'border-spacing', 'border-style', 'border-top',
+    'border-top-color', 'border-top-style', 'border-top-width',
+    'border-width', bottom, br, braille, brown, browser, burlywood, button,
     buttonface, buttonhighlight, buttonshadow, buttontext, bytesToUIString,
     c, cadetblue, call, callee, caller, canvas, cap, caption,
-    "caption-side", captiontext, center, charAt, charCodeAt, character,
+    'caption-side', captiontext, center, charAt, charCodeAt, character,
     chartreuse, chocolate, chooseColor, chooseFile, chooseFolder, cite,
     clear, clearInterval, clearTimeout, clip, closeWidget, closure, cm,
     code, col, colgroup, color, combine_var, command, comment, comments,
     concat, conditional_assignment, confirm, confusing_a, confusing_regexp,
     console, constructor, constructor_name_a, content, continue, control_a,
     convertPathToHFS, convertPathToPlatform, coral, cornflowerblue,
-    cornsilk, "counter-increment", "counter-reset", create, crimson, css,
+    cornsilk, 'counter-increment', 'counter-reset', create, crimson, css,
     cursor, cyan, d, dangerous_comment, dangling_a, darkblue, darkcyan,
     darkgoldenrod, darkgray, darkgreen, darkkhaki, darkmagenta,
     darkolivegreen, darkorange, darkorchid, darkred, darksalmon,
@@ -265,7 +258,7 @@
     deepskyblue, defineClass, del, deleted, deserialize, details, devel,
     dfn, dialog, dimgray, dir, direction, display, disrupt, div, dl,
     document, dodgerblue, dt, duplicate_a, edge, edition, else, em, embed,
-    embossed, empty, "empty-cells", empty_block, empty_case, empty_class,
+    embossed, empty, 'empty-cells', empty_block, empty_case, empty_class,
     encodeURI, encodeURIComponent, entityify, errors, es5, escape, eval,
     event, evidence, evil, ex, exception, exec, expected_a,
     expected_a_at_b_c, expected_a_b, expected_a_b_from_c_d, expected_at_a,
@@ -277,89 +270,90 @@
     expected_positive_a, expected_pseudo_a, expected_selector_a,
     expected_small_a, expected_space_a_b, expected_string_a,
     expected_style_attribute, expected_style_pattern, expected_tagname_a,
-    fieldset, figure, filesystem, filter, firebrick, first, float, floor,
-    floralwhite, focusWidget, font, "font-family", "font-size",
-    "font-size-adjust", "font-stretch", "font-style", "font-variant",
-    "font-weight", footer, for_if, forestgreen, forEach, forin, form, fragment,
-    frame, frames, frameset, from, fromCharCode, fuchsia, fud, funct,
-    function, function_block, function_eval, function_loop,
-    function_statement, function_strict, functions, g, gainsboro, gc,
-    ghostwhite, global, globals, gold, goldenrod, gray, graytext,
-    green, greenyellow, h1, h2, h3, h4, h5, h6, handheld, hasOwnProperty,
-    head, header, height, help, hgroup, highlight, highlighttext, history,
-    honeydew, hotpink, hr, "hta:application", html, html_confusion_a,
-    html_handlers, i, iTunes, id, identifier, identifier_function, iframe,
-    img, immed, implied_evil, implieds, in, inactiveborder, inactivecaption,
-    inactivecaptiontext, include, indent, indexOf, indianred, indigo,
-    infix_in, infobackground, infotext, init, input, ins, insecure_a,
-    isAlpha, isApplicationRunning, isArray, isDigit, isFinite, isNaN, ivory,
-    join, jslint, json, kbd, keygen, keys, khaki, konfabulatorVersion,
-    label, label_a_b, labeled, lang, lastIndexOf, lavender, lavenderblush,
-    lawngreen, lbp, leading_decimal_a, led, left, legend, lemonchiffon,
-    length, "letter-spacing", li, lib, lightblue, lightcoral, lightcyan,
-    lightgoldenrodyellow, lightgreen, lightpink, lightsalmon, lightseagreen,
-    lightskyblue, lightslategray, lightsteelblue, lightyellow, lime,
-    limegreen, line, "line-height", linen, link, "list-style",
-    "list-style-image", "list-style-position", "list-style-type", load,
-    loadClass, localStorage, location, log, m, magenta, map, margin,
-    "margin-bottom", "margin-left", "margin-right", "margin-top", mark,
-    "marker-offset", maroon, match, "max-height", "max-width", maxerr,
-    maxlen, md5, mediumaquamarine, mediumblue, mediumorchid, mediumpurple,
-    mediumseagreen, mediumslateblue, mediumspringgreen, mediumturquoise,
-    mediumvioletred, member, menu, menutext, message, meta, meter,
-    midnightblue, "min-height", "min-width", mintcream, missing_a,
-    missing_a_after_b, missing_option, missing_property, missing_space_a_b,
-    missing_url, missing_use_strict, mistyrose, mixed, mm, moccasin, mode,
-    module, move_invocation, move_var, name, name_function, nav,
-    navajowhite, navigator, navy, nested_comment, newcap, next, node,
-    noframes, nomen, noscript, not, not_a_constructor, not_a_defined,
-    not_a_function, not_a_label, not_a_scope, not_greater, nud, object, ol,
-    oldlace, olive, olivedrab, on, onevar, opacity, open, openURL, opera,
-    optgroup, option, orange, orangered, orchid, outer, outline,
-    "outline-color", "outline-style", "outline-width", output, overflow,
-    "overflow-x", "overflow-y", p, padding, "padding-bottom",
-    "padding-left", "padding-right", "padding-top", "page-break-after",
-    "page-break-before", palegoldenrod, palegreen, paleturquoise,
-    palevioletred, papayawhip, param, parameter_a_get_b, parameter_set_a,
-    paren, parent, parseFloat, parseInt, passfail, pc, peachpuff, peru,
-    pink, play, plum, plusplus, pop, popupMenu, position, postscript,
-    powderblue, pre, predef, preferenceGroups, preferences, prev, print,
-    process, progress, projection, prompt, prototype, pt, purple, push, px,
-    q, querystring, quit, quote, quotes, radix, random, range, raw,
-    readFile, readUrl, read_only, reason, red, redefinition_a, regexp,
-    reloadWidget, replace, report, require, reserved, reserved_a,
-    resolvePath, resumeUpdates, rhino, right, rosybrown, royalblue, rp, rt,
-    ruby, runCommand, runCommandInBg, saddlebrown, safe, salmon, samp,
-    sandybrown, saveAs, savePreferences, scanned_a_b, screen, script,
-    scrollbar, seagreen, seal, search, seashell, second, section, select,
-    serialize, sessionStorage, setInterval, setTimeout, shift,
-    showWidgetPreferences, sienna, silver, skyblue, slash_equal, slateblue,
-    slategray, sleep, slice, small, snow, sort, source, span, spawn, speak,
-    speech, split, springgreen, src, stack, statement_block, steelblue,
-    stopping, strange_loop, strict, strong, style, styleproperty, sub,
-    subscript, substr, sup, supplant, suppressUpdates, sync, system, table,
-    "table-layout", tag_a_in_b, tan, tbody, td, teal, tellWidget, test,
-    "text-align", "text-decoration", "text-indent", "text-shadow",
-    "text-transform", textarea, tfoot, th, thead, third, thistle,
-    threeddarkshadow, threedface, threedhighlight, threedlightshadow,
-    threedshadow, thru, time, title, toLowerCase, toString, toUpperCase,
-    toint32, token, tomato, too_long, too_many, top, tr, trailing_decimal_a,
-    tree, tt, tty, turquoise, tv, type, typeof, u, ul, unclosed,
-    unclosed_comment, unclosed_regexp, undef, unescape, unescaped_a,
-    unexpected_a, unexpected_char_a_b, unexpected_comment,
-    unexpected_property_a, unexpected_space_a_b, "unicode-bidi",
-    unnecessary_initialize, unnecessary_use, unreachable_a_b,
-    unrecognized_style_attribute_a, unrecognized_tag_a, unparam, unsafe, unused,
-    unwatch, updateNow, url, urls, use_array, use_braces, use_object, use_param,
-    used_before_a, util, value, valueOf, var, var_a_not, version,
-    "vertical-align", video, violet, visibility, was, watch,
+    exports, f, fieldset, figure, filesystem, filter, firebrick, first,
+    float, floor, floralwhite, focusWidget, font, 'font-family',
+    'font-size', 'font-size-adjust', 'font-stretch', 'font-style',
+    'font-variant', 'font-weight', footer, forEach, for_if, forestgreen,
+    forin, form, fragment, frame, frames, frameset, from, fromCharCode,
+    fuchsia, fud, funct, function, function_block, function_eval,
+    function_loop, function_statement, function_strict, functions, g,
+    gainsboro, gc, ghostwhite, global, globals, gold, goldenrod, gray,
+    graytext, green, greenyellow, h1, h2, h3, h4, h5, h6, handheld,
+    hasOwnProperty, head, header, height, help, hgroup, highlight,
+    highlighttext, history, honeydew, hotpink, hr, 'hta:application', html,
+    html_confusion_a, html_handlers, i, iTunes, id, identifier,
+    identifier_function, iframe, img, immed, implied_evil, in,
+    inactiveborder, inactivecaption, inactivecaptiontext, include, indent,
+    indexOf, indianred, indigo, infix_in, infobackground, infotext, init,
+    input, ins, insecure_a, isAlpha, isApplicationRunning, isArray, isDigit,
+    isFinite, isNaN, ivory, join, jslint, json, kbd, keygen, keys, khaki,
+    konfabulatorVersion, label, label_a_b, labeled, lang, lastIndexOf,
+    lavender, lavenderblush, lawngreen, lbp, leading_decimal_a, led, left,
+    legend, lemonchiffon, length, 'letter-spacing', li, lib, lightblue,
+    lightcoral, lightcyan, lightgoldenrodyellow, lightgreen, lightpink,
+    lightsalmon, lightseagreen, lightskyblue, lightslategray,
+    lightsteelblue, lightyellow, lime, limegreen, line, 'line-height',
+    linen, link, 'list-style', 'list-style-image', 'list-style-position',
+    'list-style-type', load, loadClass, localStorage, location, log, m,
+    magenta, map, margin, 'margin-bottom', 'margin-left', 'margin-right',
+    'margin-top', mark, 'marker-offset', maroon, match, 'max-height',
+    'max-width', maxerr, maxlen, md5, mediumaquamarine, mediumblue,
+    mediumorchid, mediumpurple, mediumseagreen, mediumslateblue,
+    mediumspringgreen, mediumturquoise, mediumvioletred, member, menu,
+    menutext, message, meta, meter, midnightblue, 'min-height', 'min-width',
+    mintcream, missing_a, missing_a_after_b, missing_option,
+    missing_property, missing_space_a_b, missing_url, missing_use_strict,
+    mistyrose, mixed, mm, moccasin, mode, module, move_invocation, move_var,
+    n, name, name_function, nav, navajowhite, navigator, navy,
+    nested_comment, newcap, next, node, noframes, nomen, noscript, not,
+    not_a_constructor, not_a_defined, not_a_function, not_a_label,
+    not_a_scope, not_greater, nud, object, ol, oldlace, olive, olivedrab,
+    on, onevar, opacity, open, openURL, opera, optgroup, option, orange,
+    orangered, orchid, outer, outline, 'outline-color', 'outline-style',
+    'outline-width', output, overflow, 'overflow-x', 'overflow-y', p,
+    padding, 'padding-bottom', 'padding-left', 'padding-right',
+    'padding-top', 'page-break-after', 'page-break-before', palegoldenrod,
+    palegreen, paleturquoise, palevioletred, papayawhip, param,
+    parameter_a_get_b, parameter_set_a, paren, parent, parseFloat, parseInt,
+    passfail, pc, peachpuff, peru, pink, play, plum, plusplus, pop,
+    popupMenu, position, postscript, powderblue, pre, predef,
+    preferenceGroups, preferences, prev, print, process, progress,
+    projection, prompt, prototype, pt, purple, push, px, q, querystring,
+    quit, quote, quotes, r, radix, random, range, raw, readFile, readUrl,
+    read_only, reason, red, redefinition_a, regexp, reloadWidget, replace,
+    report, require, reserved, reserved_a, resolvePath, resumeUpdates,
+    rhino, right, rosybrown, royalblue, rp, rt, ruby, runCommand,
+    runCommandInBg, saddlebrown, safe, salmon, samp, sandybrown, saveAs,
+    savePreferences, scanned_a_b, screen, script, scrollbar, seagreen, seal,
+    search, seashell, second, section, select, serialize, sessionStorage,
+    setInterval, setTimeout, shift, showWidgetPreferences, sienna, silver,
+    skyblue, slash_equal, slateblue, slategray, sleep, slice, small, snow,
+    sort, source, span, spawn, speak, speech, split, springgreen, src,
+    stack, statement_block, steelblue, stopping, strange_loop, strict,
+    strong, style, styleproperty, sub, subscript, substr, sup, supplant,
+    suppressUpdates, sync, system, t, table, 'table-layout', tag_a_in_b,
+    tan, tbody, td, teal, tellWidget, test, 'text-align', 'text-decoration',
+    'text-indent', 'text-shadow', 'text-transform', textarea, tfoot, th,
+    thead, third, thistle, threeddarkshadow, threedface, threedhighlight,
+    threedlightshadow, threedshadow, thru, time, title, toLowerCase,
+    toString, toUpperCase, toint32, token, tomato, too_long, too_many, top,
+    tr, trailing_decimal_a, tree, tt, tty, turquoise, tv, type,
+    type_inconsistency_a_b, typeof, u, ul, unclosed, unclosed_comment,
+    unclosed_regexp, undef, unescape, unescaped_a, unexpected_a,
+    unexpected_char_a_b, unexpected_comment, unexpected_property_a,
+    unexpected_space_a_b, 'unicode-bidi', unnecessary_initialize,
+    unnecessary_use, unparam, unreachable_a_b,
+    unrecognized_style_attribute_a, unrecognized_tag_a, unsafe, unused,
+    unwatch, updateNow, url, urls, use_array, use_braces, use_object, use_or,
+    use_param, used_before_a, value, valueOf, var, var_a_not, version,
+    'vertical-align', video, violet, visibility, was, watch,
     weird_assignment, weird_condition, weird_new, weird_program,
-    weird_relation, weird_ternary, wheat, white, "white-space", whitesmoke,
-    widget, width, window, windowframe, windows, windowtext, "word-spacing",
-    "word-wrap", wrap, wrap_immediate, wrap_regexp, write_is_wrong,
-    yahooCheckLogin, yahooLogin, yahooLogout, yellow, yellowgreen,
-    "z-index", "|", "~"
- */
+    weird_relation, weird_ternary, wheat, white, 'white-space', whitesmoke,
+    widget, width, window, windowframe, windows, windowtext, 'word-spacing',
+    'word-wrap', wrap, wrap_immediate, wrap_regexp, write_is_wrong,
+    writeable, yahooCheckLogin, yahooLogin, yahooLogout, yellow,
+    yellowgreen, 'z-index', '|', '~'
+*/
 
 // The global directive is used to declare global variables that can
 // be accessed by the program. If a declaration is true, then the variable
@@ -461,7 +455,6 @@ var JSLINT = (function () {
 // bundle contains the text messages.
 
         bundle = {
-            a_function: "'{a}' is a function.",
             a_label: "'{a}' is a statement label.",
             a_not_allowed: "'{a}' is not allowed.",
             a_not_defined: "'{a}' is not defined.",
@@ -623,6 +616,7 @@ var JSLINT = (function () {
             trailing_decimal_a: "A trailing decimal point can be confused " +
                 "with a dot: '.{a}'.",
             type: "type is unnecessary.",
+            type_inconsistency_a_b: "Type inconsistency: {a} and {b}.",
             unclosed: "Unclosed string.",
             unclosed_comment: "Unclosed comment.",
             unclosed_regexp: "Unclosed regular expression.",
@@ -643,6 +637,7 @@ var JSLINT = (function () {
             use_array: "Use the array literal notation [].",
             use_braces: "Spaces are hard to count. Use {{a}}.",
             use_object: "Use the object literal notation {}.",
+            use_or: "Use the || operator.",
             use_param: "Use a named parameter.",
             used_before_a: "'{a}' was used before it was defined.",
             var_a_not: "Variable {a} was not declared correctly.",
@@ -852,6 +847,17 @@ var JSLINT = (function () {
         css_media,
         css_overflow,
 
+        descapes = {
+            'b': '\b',
+            't': '\t',
+            'n': '\n',
+            'f': '\f',
+            'r': '\r',
+            '"': '"',
+            '/': '/',
+            '\\': '\\'
+        },
+
         devel = {
             alert           : false,
             confirm         : false,
@@ -873,14 +879,19 @@ var JSLINT = (function () {
             '\\': '\\\\'
         },
 
-        funct,          // The current function
+        funct,          // The current function, including the labels used
+                        // in the function, as well as (verb), (context),
+                        // (statement), (name), (params), (complexity),
+                        // (loopage), (breakage), (onevar)
 
         functionicity = [
-            'closure', 'exception', 'global', 'label', 'outer', 'unused', 'var'
+            'closure', 'exception', 'global', 'label', 'outer', 'undef',
+            'unused', 'var'
         ],
 
         functions,      // All of the functions
-        global,         // The global scope
+        global_funct,   // The global body
+        global_scope,   // The global scope
         html_tag = {
             a:        {},
             abbr:     {},
@@ -1000,10 +1011,11 @@ var JSLINT = (function () {
         },
 
         ids,            // HTML ids
-        implied,        // Implied globals
         in_block,
         indent,
+        itself,         //  JSLint itself
         json_mode,
+        lex,            // the tokenizer
         lines,
         lookahead,
         member,
@@ -1012,6 +1024,7 @@ var JSLINT = (function () {
             clearInterval: false,
             clearTimeout : false,
             console      : false,
+            exports      : false,
             global       : false,
             module       : false,
             process      : false,
@@ -1019,22 +1032,22 @@ var JSLINT = (function () {
             require      : false,
             setInterval  : false,
             setTimeout   : false,
-            util         : false,
             __filename   : false,
             __dirname    : false
         },
+        node_js,
         numbery = {
             indexOf     : true,
             lastIndexOf : true,
             search      : true
         },
-        properties,
         next_token,
         older_token,
         option,
         predefined,     // Global variables defined by option
         prereg,
         prev_token,
+        properties,
         regexp_flag = {
             g: true,
             i: true,
@@ -1060,7 +1073,7 @@ var JSLINT = (function () {
             version     : false
         },
 
-        scope,      // The current scope
+        scope,      // An object containing an object for each variable in scope
         semicolon_coda = {
             ';' : true,
             '"' : true,
@@ -1085,7 +1098,6 @@ var JSLINT = (function () {
             'eval'              : false,
             EvalError           : false,
             Function            : false,
-            hasOwnProperty      : false,
             isFinite            : false,
             isNaN               : false,
             JSON                : false,
@@ -1233,6 +1245,8 @@ var JSLINT = (function () {
 
 // unsafe comment or string
         ax = /@cc|<\/?|script|\]\s*\]|<\s*!|&lt/i,
+// linefeed, or carriage return, or carriage return linefeed
+        crlfx = /\n|\r\n?/,
 // unsafe characters that are silently deleted by one or more browsers
         cx = /[\u0000-\u001f\u007f-\u009f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/,
 // query characters for ids
@@ -1310,7 +1324,7 @@ var JSLINT = (function () {
         };
     }
 
-    if (!Object.hasOwnProperty('create')) {
+    if (!Object.prototype.hasOwnProperty.call(Object, 'create')) {
         Object.create = function (o) {
             F.prototype = o;
             return new F();
@@ -1329,8 +1343,6 @@ var JSLINT = (function () {
         };
     }
 
-// Substandard methods
-
     if (typeof String.prototype.entityify !== 'function') {
         String.prototype.entityify = function () {
             return this
@@ -1368,39 +1380,44 @@ var JSLINT = (function () {
 
 //  Escapify a troublesome character.
 
-        return escapes[a] ? escapes[a] :
+        return escapes[a] ||
             '\\u' + ('0000' + a.charCodeAt().toString(16)).slice(-4);
     }
 
 
-    function combine(a, b) {
-        var name;
-        for (name in b) {
-            if (Object.prototype.hasOwnProperty.call(b, name)) {
-                a[name] = b[name];
-            }
-        }
+    function add_to_predefined(group) {
+        Object.keys(group).forEach(function (name) {
+            predefined[name] = group[name];
+        });
     }
 
+
     function assume() {
         if (!option.safe) {
             if (option.rhino) {
-                combine(predefined, rhino);
+                add_to_predefined(rhino);
+                option.rhino = false;
             }
             if (option.devel) {
-                combine(predefined, devel);
+                add_to_predefined(devel);
+                option.devel = false;
             }
             if (option.browser) {
-                combine(predefined, browser);
+                add_to_predefined(browser);
+                option.browser = false;
             }
             if (option.windows) {
-                combine(predefined, windows);
+                add_to_predefined(windows);
+                option.windows = false;
             }
             if (option.node) {
-                combine(predefined, node);
+                add_to_predefined(node);
+                option.node = false;
+                node_js = true;
             }
             if (option.widget) {
-                combine(predefined, widget);
+                add_to_predefined(widget);
+                option.widget = false;
             }
         }
     }
@@ -1486,7 +1503,7 @@ var JSLINT = (function () {
 
 // lexical analysis and token construction
 
-    var lex = (function lex() {
+    lex = (function lex() {
         var character, from, line, source_row;
 
 // Private lex methods
@@ -1587,14 +1604,8 @@ var JSLINT = (function () {
 
         return {
             init: function (source) {
-                if (typeof source === 'string') {
-                    lines = source
-                        .replace(/\r\n/g, '\n')
-                        .replace(/\r/g, '\n')
-                        .split('\n');
-                } else {
-                    lines = source;
-                }
+                lines = typeof source === 'string' ?
+                    source.split(crlfx) : source;
                 line = 0;
                 next_line();
                 from = 1;
@@ -1631,7 +1642,8 @@ var JSLINT = (function () {
 // token -- this is called by advance to get the next token.
 
             token: function () {
-                var b, c, captures, digit, depth, flag, high, i, j, length, low, quote, symbol;
+                var b, bit, c, captures, digit, depth, flag, high, i, j,
+                    length, low, quote, symbol;
 
                 function match(x) {
                     var exec = x.exec(source_row), first;
@@ -1726,30 +1738,11 @@ var JSLINT = (function () {
                                 case xquote:
                                     warn_at('bad_html', line, character + j);
                                     break;
-                                case '\\':
-                                case '"':
-                                case '/':
-                                    break;
                                 case '\'':
                                     if (json_mode) {
                                         warn_at('unexpected_a', line, character, '\\\'');
                                     }
                                     break;
-                                case 'b':
-                                    c = '\b';
-                                    break;
-                                case 'f':
-                                    c = '\f';
-                                    break;
-                                case 'n':
-                                    c = '\n';
-                                    break;
-                                case 'r':
-                                    c = '\r';
-                                    break;
-                                case 't':
-                                    c = '\t';
-                                    break;
                                 case 'u':
                                     hex(4);
                                     break;
@@ -1766,7 +1759,10 @@ var JSLINT = (function () {
                                     hex(2);
                                     break;
                                 default:
-                                    warn_at('unexpected_a', line, character, '\\');
+                                    c = descapes[c];
+                                    if (typeof c !== 'string') {
+                                        warn_at('unexpected_a', line, character, '\\');
+                                    }
                                 }
                             }
                         }
@@ -2009,11 +2005,11 @@ var JSLINT = (function () {
                                                     line, from + length, '^');
                                             }
                                         }
-                                        quote = false;
+                                        bit = false;
                                         if (c === ']') {
                                             warn_at('empty_class', line,
                                                 from + length - 1);
-                                            quote = true;
+                                            bit = true;
                                         }
 klass:                                  do {
                                             c = source_row.charAt(length);
@@ -2023,19 +2019,19 @@ klass:                                  do {
                                             case '^':
                                                 warn_at('unescaped_a',
                                                     line, from + length, c);
-                                                quote = true;
+                                                bit = true;
                                                 break;
                                             case '-':
-                                                if (quote) {
-                                                    quote = false;
+                                                if (bit) {
+                                                    bit = false;
                                                 } else {
                                                     warn_at('unescaped_a',
                                                         line, from + length, '-');
-                                                    quote = true;
+                                                    bit = true;
                                                 }
                                                 break;
                                             case ']':
-                                                if (!quote) {
+                                                if (!bit) {
                                                     warn_at('unescaped_a',
                                                         line, from + length - 1, '-');
                                                 }
@@ -2058,12 +2054,12 @@ klass:                                  do {
                                                     );
                                                 }
                                                 length += 1;
-                                                quote = true;
+                                                bit = true;
                                                 break;
                                             case '/':
                                                 warn_at('unescaped_a',
                                                     line, from + length - 1, '/');
-                                                quote = true;
+                                                bit = true;
                                                 break;
                                             case '<':
                                                 if (xmode === 'script') {
@@ -2077,10 +2073,10 @@ klass:                                  do {
                                                         );
                                                     }
                                                 }
-                                                quote = true;
+                                                bit = true;
                                                 break;
                                             default:
-                                                quote = true;
+                                                bit = true;
                                             }
                                         } while (c);
                                         break;
@@ -2200,7 +2196,7 @@ klass:                                  do {
 
                         case '<!--':
                             length = line;
-                            c = character;
+//                            c = character;
                             for (;;) {
                                 i = source_row.indexOf('--');
                                 if (i >= 0) {
@@ -2277,36 +2273,54 @@ klass:                                  do {
     }());
 
 
-    function add_label(symbol, type) {
+    function add_label(token, kind, name) {
 
-        if (option.safe && funct['(global)'] &&
-                typeof predefined[symbol] !== 'boolean') {
-            warn('adsafe_a', token, symbol);
-        } else if (symbol === 'hasOwnProperty') {
-            warn('bad_name_a', token, symbol);
-        }
+// Define the symbol in the current function in the current scope.
 
-// Define symbol in the current function in the current scope.
+        name = name || token.value;
 
-        if (Object.prototype.hasOwnProperty.call(funct, symbol) && !funct['(global)']) {
-            warn(funct[symbol] === true ?
-                bundle.used_before_a :
-                bundle.already_defined,
-                next_token, symbol);
-        }
-        funct[symbol] = type;
-        if (funct['(global)']) {
-            if (global[symbol] === false) {
-                warn('read_only');
+// Global variables cannot be created in the safe subset. If a global variable
+// already exists, do nothing. If it is predefined, define it.
+
+        if (funct === global_funct) {
+            if (option.safe) {
+                warn('adsafe_a', token, name);
+            }
+            if (typeof global_funct[name] !== 'string') {
+                token.writeable = typeof predefined[name] === 'boolean' ?
+                    predefined[name] : true;
+                token.funct = funct;
+                global_scope[name] = token;
             }
-            global[symbol] = true;
-            if (Object.prototype.hasOwnProperty.call(implied, symbol)) {
-                warn('used_before_a', next_token, symbol);
-                delete implied[symbol];
+            if (kind === 'becoming') {
+                kind = 'var';
             }
+
+// Ordinary variables.
+
         } else {
-            scope[symbol] = funct;
+
+// Warn if the variable already exists.
+
+            if (typeof funct[name] === 'string') {
+                if (funct[name] === 'undef') {
+                    if (option.undef) {
+                        warn('used_before_a', token, name);
+                    }
+                    kind = 'var';
+                } else {
+                    warn('already_defined', token, name);
+                }
+            } else {
+
+// Add the symbol to the current function.
+
+                token.funct = funct;
+                token.writeable = true;
+                scope[name] = token;
+            }
         }
+        funct[name] = kind;
     }
 
 
@@ -2375,7 +2389,7 @@ klass:                                  do {
                     }
                     dent.open = false;
                 }
-                var_mode = false;
+                var_mode = null;
             }
             if (indent.open) {
 
@@ -2431,7 +2445,7 @@ klass:                                  do {
             }
             break;
         }
-        if (token.arity === 'string' || token.identifier) {
+        if (token.id === '(string)' || token.identifier) {
             anonname = token.value;
         }
 
@@ -2452,12 +2466,159 @@ klass:                                  do {
     }
 
 
+    function do_safe() {
+        if (option.adsafe) {
+            option.safe = true;
+        }
+        if (option.safe) {
+            option.browser     =
+                option['continue'] =
+                option.css     =
+                option.debug   =
+                option.devel   =
+                option.evil    =
+                option.forin   =
+                option.on      =
+                option.rhino   =
+                option.sub     =
+                option.widget  =
+                option.windows = false;
+
+            option.newcap      =
+                option.nomen   =
+                option.strict  =
+                option.undef   = true;
+
+            delete predefined.Date;
+            delete predefined['eval'];
+            delete predefined.Function;
+            delete predefined.Object;
+            delete predefined.Array;
+            delete predefined.String;
+            delete predefined.Number;
+
+            add_to_predefined({
+                ADSAFE: false,
+                lib: false
+            });
+        }
+    }
+
+
+    function do_globals() {
+        var name, writeable;
+        for (;;) {
+            if (next_token.id !== '(string)' && !next_token.identifier) {
+                return;
+            }
+            name = next_token.value;
+            advance();
+            writeable = false;
+            if (next_token.id === ':') {
+                advance(':');
+                switch (next_token.id) {
+                case 'true':
+                    writeable = predefined[name] !== false;
+                    advance('true');
+                    break;
+                case 'false':
+                    advance('false');
+                    break;
+                default:
+                    stop('unexpected_a');
+                }
+            }
+            predefined[name] = writeable;
+            if (next_token.id !== ',') {
+                return;
+            }
+            advance(',');
+        }
+    }
+
+
+    function do_jslint() {
+        var name, value;
+        while (next_token.id === '(string)' || next_token.identifier) {
+            name = next_token.value;
+            advance();
+            if (next_token.id !== ':') {
+                stop('expected_a_b', next_token, ':', next_token.value);
+            }
+            advance(':');
+            switch (name) {
+            case 'indent':
+                value = +next_token.value;
+                if (typeof value !== 'number' ||
+                        !isFinite(value) || value < 0 ||
+                        Math.floor(value) !== value) {
+                    stop('expected_small_a');
+                }
+                option.indent = value;
+                break;
+            case 'maxerr':
+                value = +next_token.value;
+                if (typeof value !== 'number' ||
+                        !isFinite(value) ||
+                        value <= 0 ||
+                        Math.floor(value) !== value) {
+                    stop('expected_small_a', next_token);
+                }
+                option.maxerr = value;
+                break;
+            case 'maxlen':
+                value = +next_token.value;
+                if (typeof value !== 'number' || !isFinite(value) || value < 0 ||
+                        Math.floor(value) !== value) {
+                    stop('expected_small_a');
+                }
+                option.maxlen = value;
+                break;
+            default:
+                if (next_token.id === 'true') {
+                    option[name] = true;
+                } else if (next_token.id === 'false') {
+                    option[name] = false;
+                } else {
+                    stop('unexpected_a');
+                }
+                if (name === 'adsafe') {
+                    option.adsafe = option.safe = true;
+                    do_safe();
+                } else if (name === 'safe') {
+                    do_safe();
+                }
+            }
+            advance();
+            if (next_token.id === ',') {
+                advance(',');
+            }
+        }
+        assume();
+    }
+
+
+    function do_properties() {
+        if (!properties) {
+            properties = {};
+        }
+        for (;;) {
+            if (next_token.id !== '(string)' && !next_token.identifier) {
+                return;
+            }
+            properties[next_token.value] = true;
+            advance();
+            if (next_token.id !== ',') {
+                return;
+            }
+            advance(',');
+        }
+    }
+
+
     function directive() {
         var command = this.id,
-            name,
-            old_comments_off = comments_off,
-            old_option_white = option.white,
-            value;
+            old_comments_off = comments_off;
         if (next_token.line === token.line && next_token.from === token.thru) {
             warn('missing_space_a_b', next_token, token.value, next_token.value);
         }
@@ -2471,140 +2632,26 @@ klass:                                  do {
         case '/*property':
         case '/*members':
         case '/*member':
-            command = '/*properties';
-            if (!properties) {
-                properties = {};
-            }
+            do_properties();
             break;
         case '/*jslint':
             if (option.safe) {
                 warn('adsafe_a', this);
             }
+            do_jslint();
             break;
         case '/*globals':
         case '/*global':
-            command = '/*global';
             if (option.safe) {
                 warn('adsafe_a', this);
             }
+            do_globals();
             break;
         default:
             stop('unpexpected_a', this);
         }
-loop:   for (;;) {
-            for (;;) {
-                if (next_token.id === '*/') {
-                    break loop;
-                }
-                if (next_token.id !== ',') {
-                    break;
-                }
-                advance();
-            }
-            if (next_token.arity !== 'string' && !next_token.identifier) {
-                stop('unexpected_a', next_token);
-            }
-            name = next_token.value;
-            advance();
-            switch (command) {
-            case '/*global':
-                if (next_token.id === ':') {
-                    advance(':');
-                    switch (next_token.id) {
-                    case 'true':
-                        if (typeof scope[name] === 'object' ||
-                                global[name] === false) {
-                            stop('unexpected_a');
-                        }
-                        global[name] = true;
-                        advance('true');
-                        break;
-                    case 'false':
-                        if (typeof scope[name] === 'object') {
-                            stop('unexpected_a');
-                        }
-                        global[name] = false;
-                        advance('false');
-                        break;
-                    default:
-                        stop('unexpected_a');
-                    }
-                } else {
-                    if (typeof scope[name] === 'object') {
-                        stop('unexpected_a');
-                    }
-                    global[name] = false;
-                }
-                break;
-            case '/*jslint':
-                if (next_token.id !== ':') {
-                    stop('expected_a_b', next_token, ':', next_token.value);
-                }
-                advance(':');
-                switch (name) {
-                case 'indent':
-                    value = +next_token.value;
-                    if (typeof value !== 'number' ||
-                            !isFinite(value) || value < 0 ||
-                            Math.floor(value) !== value) {
-                        stop('expected_small_a');
-                    }
-                    if (value > 0) {
-                        old_option_white = true;
-                    }
-                    option.indent = value;
-                    break;
-                case 'maxerr':
-                    value = +next_token.value;
-                    if (typeof value !== 'number' ||
-                            !isFinite(value) ||
-                            value <= 0 ||
-                            Math.floor(value) !== value) {
-                        stop('expected_small_a', next_token);
-                    }
-                    option.maxerr = value;
-                    break;
-                case 'maxlen':
-                    value = +next_token.value;
-                    if (typeof value !== 'number' || !isFinite(value) || value < 0 ||
-                            Math.floor(value) !== value) {
-                        stop('expected_small_a');
-                    }
-                    option.maxlen = value;
-                    break;
-                case 'white':
-                    if (next_token.id === 'true') {
-                        old_option_white = true;
-                    } else if (next_token.id === 'false') {
-                        old_option_white = false;
-                    } else {
-                        stop('unexpected_a');
-                    }
-                    break;
-                default:
-                    if (next_token.id === 'true') {
-                        option[name] = true;
-                    } else if (next_token.id === 'false') {
-                        option[name] = false;
-                    } else {
-                        stop('unexpected_a');
-                    }
-                }
-                advance();
-                break;
-            case '/*properties':
-                properties[name] = true;
-                break;
-            default:
-                stop('unexpected_a');
-            }
-        }
-        if (command === '/*jslint') {
-            assume();
-        }
         comments_off = old_comments_off;
         advance('*/');
-        option.white = old_option_white;
     }
 
 
@@ -2780,7 +2827,7 @@ loop:   for (;;) {
             case 'prefix':
             case 'suffix':
             case undefined:
-                return are_similar(a.first, b.first);
+                return a.id === b.id && are_similar(a.first, b.first);
             case 'infix':
                 return are_similar(a.first, b.first) &&
                     are_similar(a.second, b.second);
@@ -2796,9 +2843,9 @@ loop:   for (;;) {
             }
         } else {
             if (a.id === '.' && b.id === '[' && b.arity === 'infix') {
-                return a.second.value === b.second.value && b.second.arity === 'string';
+                return a.second.value === b.second.value && b.second.id === '(string)';
             } else if (a.id === '[' && a.arity === 'infix' && b.id === '.') {
-                return a.second.value === b.second.value && a.second.arity === 'string';
+                return a.second.value === b.second.value && a.second.id === '(string)';
             }
         }
         return false;
@@ -2829,7 +2876,7 @@ loop:   for (;;) {
             stop('unexpected_a', token, next_token.id);
         }
         advance();
-        if (option.safe && typeof predefined[token.value] === 'boolean' &&
+        if (option.safe && scope[token.value] === global_scope[token.value] &&
                 (next_token.id !== '(' && next_token.id !== '.')) {
             warn('adsafe', token);
         }
@@ -2843,7 +2890,7 @@ loop:   for (;;) {
             if (token.nud) {
                 left = token.nud();
             } else {
-                if (next_token.arity === 'number' && token.id === '.') {
+                if (next_token.id === '(number)' && token.id === '.') {
                     warn('leading_decimal_a', token,
                         next_token.value);
                     advance();
@@ -2954,9 +3001,9 @@ loop:   for (;;) {
     }
 
 
-    function type(s, arity, nud) {
+    function type(s, t, nud) {
         var x = delim(s);
-        x.arity = arity;
+        x.arity = x.type = t;
         if (nud) {
             x.nud = nud;
         }
@@ -2964,6 +3011,35 @@ loop:   for (;;) {
     }
 
 
+    function conform_type(one, two) {
+        var a = (one.identifier && scope[one.value]) || one,
+            b = (two.identifier && scope[two.value]) || two,
+            match = '';
+        if (a.type) {
+            if (b.type) {
+                if (a.type === b.type) {
+                    match = a.type;
+                } else {
+                    if (!option.type) {
+                        warn('type_inconsistency_a_b', two, a.type, b.type);
+                    }
+                }
+            } else {
+                if (b.id !== 'null' && b.id !== 'undefined') {
+                    b.type = a.type;
+                }
+                match = a.type;
+            }
+        } else if (b.type) {
+            if (a.id !== 'null' && a.id !== 'undefined') {
+                a.type = b.type;
+            }
+            match = b.type;
+        }
+        return match;
+    }
+
+
     function reserve(s, f) {
         var x = delim(s);
         x.identifier = x.reserved = true;
@@ -2974,6 +3050,15 @@ loop:   for (;;) {
     }
 
 
+    function constant(name, type, value) {
+        var x = reserve(name);
+        x.type = type;
+        x.value = value;
+        x.nud = return_this;
+        return x;
+    }
+
+
     function reservevar(s, v) {
         return reserve(s, function () {
             if (typeof v === 'function') {
@@ -2984,7 +3069,7 @@ loop:   for (;;) {
     }
 
 
-    function infix(s, p, f, w) {
+    function infix(s, p, f, type, w) {
         var x = symbol(s, p);
         reserve_name(x);
         x.led = function (left) {
@@ -2993,6 +3078,9 @@ loop:   for (;;) {
                 spaces(prev_token, token);
                 spaces();
             }
+            if (option.bitwise && this.bitwise) {
+                warn('unexpected_a', this);
+            }
             if (typeof f === 'function') {
                 return f(left, this);
             } else {
@@ -3001,6 +3089,9 @@ loop:   for (;;) {
                 return this;
             }
         };
+        if (type) {
+            x.type = type;
+        }
         return x;
     }
 
@@ -3069,38 +3160,32 @@ loop:   for (;;) {
 
 
     function relation(s, eqeq) {
-        var x = infix(s, 100, function (left, that) {
+        return infix(s, 100, function (left, that) {
             check_relation(left);
             if (eqeq) {
                 warn('expected_a_b', that, eqeq, that.id);
             }
             var right = expression(100);
             if (are_similar(left, right) ||
-                    ((left.arity === 'string' || left.arity === 'number') &&
-                    (right.arity === 'string' || right.arity === 'number'))) {
+                    ((left.id === '(string)' || left.id === '(number)') &&
+                    (right.id === '(string)' || right.id === '(number)'))) {
                 warn('weird_relation', that);
             }
             that.first = left;
             that.second = check_relation(right);
+            conform_type(left, that.second);
             return that;
-        });
-        return x;
+        }, 'boolean');
     }
 
 
-    function assignop(s, bit) {
+    function assignop(s, op) {
         var x = infix(s, 20, function (left, that) {
             var l;
-            if (option.bitwise && bit) {
-                warn('unexpected_a', that);
-            }
             that.first = left;
-            if (funct[left.value] === false) {
+            if (left.identifier && scope[left.value].writeable === false) {
                 warn('read_only', left);
-            } else if (left['function']) {
-                warn('a_function', left);
-            }
-            if (option.safe) {
+            } else if (option.safe) {
                 l = left;
                 do {
                     if (typeof predefined[l.value] === 'boolean') {
@@ -3109,46 +3194,51 @@ loop:   for (;;) {
                     l = l.first;
                 } while (l);
             }
-            if (left) {
-                if (left === syntax['function']) {
-                    warn('identifier_function', token);
+            if (left === syntax['function']) {
+                warn('identifier_function', token);
+            }
+            if (left.id === '.' || left.id === '[') {
+                if (!left.first || left.first.value === 'arguments') {
+                    warn('bad_assignment', that);
                 }
-                if (left.id === '.' || left.id === '[') {
-                    if (!left.first || left.first.value === 'arguments') {
-                        warn('bad_assignment', that);
-                    }
-                    that.second = expression(19);
-                    if (that.id === '=' && are_similar(that.first, that.second)) {
-                        warn('weird_assignment', that);
-                    }
-                    return that;
-                } else if (left.identifier && !left.reserved) {
-                    if (funct[left.value] === 'exception') {
-                        warn('assign_exception', left);
-                    }
-                    that.second = expression(19);
-                    if (that.id === '=' && are_similar(that.first, that.second)) {
-                        warn('weird_assignment', that);
-                    }
-                    return that;
+                that.second = expression(19);
+                if (that.id === '=' && are_similar(that.first, that.second)) {
+                    warn('weird_assignment', that);
+                }
+            } else if (left.identifier && !left.reserved) {
+                if (funct[left.value] === 'exception') {
+                    warn('assign_exception', left);
+                }
+                that.second = expression(19);
+                if (that.id === '=' && are_similar(that.first, that.second)) {
+                    warn('weird_assignment', that);
+                }
+                if (that.type) {
+                    conform_type(left, that);
+                    conform_type(that, that.second);
+                } else {
+                    conform_type(left, that.second);
                 }
             }
-            stop('bad_assignment', that);
+            return that;
         });
         x.assign = true;
+        if (op) {
+            if (syntax[op].type) {
+                x.type = syntax[op].type;
+            }
+            if (syntax[op].bitwise) {
+                x.bitwise = true;
+            }
+        }
         return x;
     }
 
 
     function bitwise(s, p) {
-        return infix(s, p, function (left, that) {
-            if (option.bitwise) {
-                warn('unexpected_a', that);
-            }
-            that.first = left;
-            that.second = expression(p);
-            return that;
-        });
+        var x = infix(s, p, 'number');
+        x.bitwise = true;
+        return x;
     }
 
 
@@ -3185,22 +3275,16 @@ loop:   for (;;) {
 
     function identifier() {
         var i = optional_identifier();
-        if (i) {
-            return i;
-        }
-        if (token.id === 'function' && next_token.id === '(') {
-            warn('name_function');
-        } else {
-            stop('expected_identifier_a');
+        if (!i) {
+            stop(token.id === 'function' && next_token.id === '(' ?
+                'name_function' : 'expected_identifier_a');
         }
+        return i;
     }
 
 
     function statement() {
 
-// Usually a statement starts a line. Exceptions include the var statement in the
-// initialization part of a for statement, and an if after an else.
-
         var label, old_scope = scope, the_statement;
 
 // We don't like the empty statement.
@@ -3221,12 +3305,13 @@ loop:   for (;;) {
             advance(':');
             discard();
             scope = Object.create(old_scope);
-            add_label(label.value, 'label');
+            add_label(label, 'label');
             if (next_token.labeled !== true) {
                 warn('label_a_b', next_token, label.value, next_token.value);
-            }
-            if (jx.test(label.value + ':')) {
+            } else if (jx.test(label.value + ':')) {
                 warn('url', label);
+            } else if (funct === global_funct) {
+                stop('unexpected_a', token);
             }
             next_token.label = label;
         }
@@ -3249,7 +3334,7 @@ loop:   for (;;) {
                 }
             } else {
 
-// If this is an expression statement, determine if it is acceptble.
+// If this is an expression statement, determine if it is acceptable.
 // We do not like
 //      new Blah();
 // statments. If it is to be used at all, new should only be used to make
@@ -3286,6 +3371,12 @@ loop:   for (;;) {
                 warn('unexpected_a', next_token);
                 semicolon();
             } else {
+                if (next_token.value === 'use strict') {
+                    if (!node_js || funct !== global_funct || array.length > 0) {
+                        warn('function_strict');
+                    }
+                    use_strict();
+                }
                 if (disruptor) {
                     warn('unreachable_a_b', next_token, next_token.value,
                         disruptor.value);
@@ -3324,7 +3415,7 @@ loop:   for (;;) {
             advance('{');
             step_in();
             if (!ordinary && !use_strict() && !old_strict_mode &&
-                    option.strict && funct['(context)']['(global)']) {
+                    option.strict && funct['(context)'] === global_funct) {
                 warn('missing_use_strict');
             }
             array = statements();
@@ -3360,32 +3451,48 @@ loop:   for (;;) {
     }
 
 
-    function note_implied(token) {
-        var name = token.value, line = token.line, a = implied[name];
-        if (typeof a === 'function') {
-            a = false;
-        }
-        if (!a) {
-            a = [line];
-            implied[name] = a;
-        } else if (a[a.length - 1] !== line) {
-            a.push(line);
-        }
-    }
-
-
 // ECMAScript parser
 
     syntax['(identifier)'] = {
-        type: '(identifier)',
         lbp: 0,
         identifier: true,
         nud: function () {
-            var variable = this.value,
-                site = scope[variable];
-            if (typeof site === 'function') {
-                site = undefined;
+            var name = this.value,
+                variable = scope[name],
+                site,
+                writeable;
+
+// If the variable is not in scope, then we may have an undeclared variable.
+// Check the predefined list. If it was predefined, create the global
+// variable.
+
+            if (typeof variable !== 'object') {
+                writeable = predefined[name];
+                if (typeof writeable === 'boolean') {
+                    global_scope[name] = variable = {
+                        value:     name,
+                        writeable: writeable,
+                        funct:     global_funct
+                    };
+                    global_funct[name] = 'var';
+
+// But if the variable is not in scope, and is not predefined, and if we are not
+// in the global scope, then we have an undefined variable error.
+
+                } else {
+                    if (option.undef) {
+                        warn('used_before_a', token);
+                    }
+                    scope[name] = variable = {
+                        value: name,
+                        writeable: true,
+                        funct: funct
+                    };
+                    funct[name] = 'undef';
+                }
+
             }
+            site = variable.funct;
 
 // The name is in scope and defined in the current function.
 
@@ -3393,105 +3500,68 @@ loop:   for (;;) {
 
 //      Change 'unused' to 'var', and reject labels.
 
-                switch (funct[variable]) {
-                case 'error':
+                switch (funct[name]) {
+                case 'becoming':
                     warn('unexpected_a', token);
-                    funct[variable] = 'var';
+                    funct[name] = 'var';
                     break;
                 case 'unused':
-                    funct[variable] = 'var';
+                    funct[name] = 'var';
                     break;
                 case 'unparam':
-                    funct[variable] = 'parameter';
+                    funct[name] = 'parameter';
                     break;
                 case 'unction':
-                    funct[variable] = 'function';
-                    this['function'] = true;
-                    break;
-                case 'function':
-                    this['function'] = true;
+                    funct[name] = 'function';
                     break;
                 case 'label':
-                    warn('a_label', token, variable);
+                    warn('a_label', token, name);
                     break;
                 }
 
-// The name is not defined in the function.  If we are in the global scope,
-// then we have an undefined variable.
-
-            } else if (funct['(global)']) {
-                if (typeof global[variable] === 'boolean') {
-                    funct[variable] = global[variable];
-                } else {
-                    if (option.undef) {
-                        warn('not_a_defined', token, variable);
-                    } else {
-                        note_implied(token);
-                    }
-                }
-
 // If the name is already defined in the current
 // function, but not as outer, then there is a scope error.
 
             } else {
-                switch (funct[variable]) {
+                switch (funct[name]) {
                 case 'closure':
                 case 'function':
                 case 'var':
                 case 'unused':
-                    warn('a_scope', token, variable);
+                    warn('a_scope', token, name);
                     break;
                 case 'label':
-                    warn('a_label', token, variable);
+                    warn('a_label', token, name);
                     break;
                 case 'outer':
-                case true:
-                case false:
+                case 'global':
                     break;
                 default:
 
 // If the name is defined in an outer function, make an outer entry, and if
 // it was unused, make it var.
 
-                    if (typeof site === 'boolean') {
-                        funct[variable] = site;
-                        functions[0][variable] = true;
-                    } else if (site === null) {
-                        warn('a_not_allowed', token, variable);
-                        note_implied(token);
-                    } else if (typeof site !== 'object') {
-                        if (option.undef) {
-                            warn('a_not_defined', token, variable);
-                        } else {
-                            funct[variable] = true;
-                        }
-                        note_implied(token);
-                    } else {
-                        switch (site[variable]) {
-                        case 'function':
-                        case 'unction':
-                            this['function'] = true;
-                            site[variable] = 'closure';
-                            funct[variable] = site['(global)'] ? false : 'outer';
-                            break;
-                        case 'var':
-                        case 'unused':
-                        case 'closure':
-                        case 'parameter':
-                            site[variable] = 'closure';
-                            funct[variable] = site['(global)'] ? true : 'outer';
-                            break;
-                        case 'unparam':
-                            site[variable] = 'parameter';
-                            funct[variable] = site['(global)'] ? false : 'outer';
-                            break;
-                        case 'error':
-                            warn('not_a_defined', token);
-                            break;
-                        case 'label':
-                            warn('a_label', token, variable);
-                            break;
-                        }
+                    switch (site[name]) {
+                    case 'function':
+                    case 'unction':
+                    case 'var':
+                    case 'unused':
+                    case 'becoming':
+                    case 'closure':
+                    case 'parameter':
+                        site[name] = 'closure';
+                        funct[name] = site === global_funct ? 'global' : 'outer';
+                        break;
+                    case 'unparam':
+                        site[name] = 'parameter';
+                        funct[name] = 'outer';
+                        break;
+                    case 'undef':
+                        funct[name] = 'undef';
+                        break;
+                    case 'label':
+                        warn('a_label', token, name);
+                        break;
                     }
                 }
             }
@@ -3507,6 +3577,7 @@ loop:   for (;;) {
     type('(color)', 'color');
     type('(number)', 'number', return_this);
     type('(string)', 'string', return_this);
+    type('(boolean)', 'boolean', return_this);
     type('(range)', 'range');
     type('(regexp)', 'regexp', return_this);
 
@@ -3535,7 +3606,7 @@ loop:   for (;;) {
     reserve('finally');
 
     reservevar('arguments', function (x) {
-        if (strict_mode && funct['(global)']) {
+        if (strict_mode && funct === global_funct) {
             warn('strict', x);
         } else if (option.safe) {
             warn('adsafe', x);
@@ -3546,35 +3617,20 @@ loop:   for (;;) {
             warn('adsafe', x);
         }
     });
-    reservevar('false');
-    reservevar('Infinity');
-    reservevar('NaN');
-    reservevar('null');
+    constant('false', 'boolean', false);
+    constant('Infinity', 'number', Infinity);
+    constant('NaN', 'number', NaN);
+    constant('null', '', null);
     reservevar('this', function (x) {
         if (strict_mode && ((funct['(statement)'] &&
-                funct['(name)'].charAt(0) > 'Z') || funct['(global)'])) {
+                funct['(name)'].charAt(0) > 'Z') || funct === global_funct)) {
             warn('strict', x);
         } else if (option.safe) {
             warn('adsafe', x);
         }
     });
-    reservevar('true');
-    reservevar('undefined');
-
-    assignop('=');
-    assignop('+=');
-    assignop('-=');
-    assignop('*=');
-    assignop('/=').nud = function () {
-        stop('slash_equal');
-    };
-    assignop('%=');
-    assignop('&=', true);
-    assignop('|=', true);
-    assignop('^=', true);
-    assignop('<<=', true);
-    assignop('>>=', true);
-    assignop('>>>=', true);
+    constant('true', 'boolean', true);
+    constant('undefined', '', undefined);
 
     infix('?', 30, function (left, that) {
         that.first = expected_condition(expected_relation(left));
@@ -3585,8 +3641,11 @@ loop:   for (;;) {
         spaces();
         that.third = expression(10);
         that.arity = 'ternary';
+        that.type = conform_type(that.second, that.third);
         if (are_similar(that.second, that.third)) {
             warn('weird_ternary', that);
+        } else if (are_similar(that.first, that.second)) {
+            warn('use_or', that);
         }
         return that;
     });
@@ -3618,10 +3677,11 @@ loop:   for (;;) {
 
     prefix('void', function () {
         this.first = expression(0);
-        if (this.first.arity !== 'number' || this.first.value) {
+        if (this.first.id !== '(number)' || this.first.value) {
             warn('unexpected_a', this);
             return this;
         }
+        this.type = 'undefined';
         return this;
     });
 
@@ -3647,29 +3707,29 @@ loop:   for (;;) {
         that.left = left;
         that.right = expression(130);
         return that;
-    });
-    infix('instanceof', 120);
+    }, 'boolean');
+    infix('instanceof', 120, null, 'boolean');
     infix('+', 130, function (left, that) {
         if (!left.value) {
-            if (left.arity === 'number') {
+            if (left.id === '(number)') {
                 warn('unexpected_a', left);
-            } else if (left.arity === 'string') {
+            } else if (left.id === '(string)') {
                 warn('expected_a_b', left, 'String', '\'\'');
             }
         }
         var right = expression(130);
         if (!right.value) {
-            if (right.arity === 'number') {
+            if (right.id === '(number)') {
                 warn('unexpected_a', right);
-            } else if (right.arity === 'string') {
+            } else if (right.id === '(string)') {
                 warn('expected_a_b', right, 'String', '\'\'');
             }
         }
-        if (left.arity === right.arity &&
-                (left.arity === 'string' || left.arity === 'number')) {
+        if (left.id === right.id &&
+                (left.id === '(string)' || left.id === '(number)')) {
             left.value += right.value;
             left.thru = right.thru;
-            if (left.arity === 'string' && jx.test(left.value)) {
+            if (left.id === '(string)' && jx.test(left.value)) {
                 warn('url', left);
             }
             discard(right);
@@ -3678,6 +3738,7 @@ loop:   for (;;) {
         }
         that.first = left;
         that.second = right;
+        that.type = conform_type(left, right);
         return that;
     });
     prefix('+', 'num');
@@ -3694,14 +3755,14 @@ loop:   for (;;) {
         return this;
     });
     infix('-', 130, function (left, that) {
-        if ((left.arity === 'number' && left.value === 0) || left.arity === 'string') {
+        if ((left.id === '(number)' && left.value === 0) || left.id === '(string)') {
             warn('unexpected_a', left);
         }
         var right = expression(130);
-        if ((right.arity === 'number' && right.value === 0) || right.arity === 'string') {
+        if ((right.id === '(number)' && right.value === 0) || right.id === '(string)') {
             warn('unexpected_a', left);
         }
-        if (left.arity === right.arity && left.arity === 'number') {
+        if (left.id === right.id && left.id === '(number)') {
             left.value -= right.value;
             left.thru = right.thru;
             discard(right);
@@ -3711,7 +3772,7 @@ loop:   for (;;) {
         that.first = left;
         that.second = right;
         return that;
-    });
+    }, 'number');
     prefix('-');
     prefix('---', function () {
         warn('confusing_a', token);
@@ -3726,14 +3787,14 @@ loop:   for (;;) {
         return this;
     });
     infix('*', 140, function (left, that) {
-        if ((left.arity === 'number' && (left.value === 0 || left.value === 1)) || left.arity === 'string') {
+        if ((left.id === '(number)' && (left.value === 0 || left.value === 1)) || left.id === '(string)') {
             warn('unexpected_a', left);
         }
         var right = expression(140);
-        if ((right.arity === 'number' && (right.value === 0 || right.value === 1)) || right.arity === 'string') {
+        if ((right.id === '(number)' && (right.value === 0 || right.value === 1)) || right.id === '(string)') {
             warn('unexpected_a', right);
         }
-        if (left.arity === right.arity && left.arity === 'number') {
+        if (left.id === right.id && left.id === '(number)') {
             left.value *= right.value;
             left.thru = right.thru;
             discard(right);
@@ -3743,16 +3804,16 @@ loop:   for (;;) {
         that.first = left;
         that.second = right;
         return that;
-    });
+    }, 'number');
     infix('/', 140, function (left, that) {
-        if ((left.arity === 'number' && left.value === 0) || left.arity === 'string') {
+        if ((left.id === '(number)' && left.value === 0) || left.id === '(string)') {
             warn('unexpected_a', left);
         }
         var right = expression(140);
-        if ((right.arity === 'number' && (right.value === 0 || right.value === 1)) || right.arity === 'string') {
+        if ((right.id === '(number)' && (right.value === 0 || right.value === 1)) || right.id === '(string)') {
             warn('unexpected_a', right);
         }
-        if (left.arity === right.arity && left.arity === 'number') {
+        if (left.id === right.id && left.id === '(number)') {
             left.value /= right.value;
             left.thru = right.thru;
             discard(right);
@@ -3762,16 +3823,16 @@ loop:   for (;;) {
         that.first = left;
         that.second = right;
         return that;
-    });
+    }, 'number');
     infix('%', 140, function (left, that) {
-        if ((left.arity === 'number' && (left.value === 0 || left.value === 1)) || left.arity === 'string') {
+        if ((left.id === '(number)' && (left.value === 0 || left.value === 1)) || left.id === '(string)') {
             warn('unexpected_a', left);
         }
         var right = expression(140);
-        if ((right.arity === 'number' && right.value === 0) || right.arity === 'string') {
+        if ((right.id === '(number)' && right.value === 0) || right.id === '(string)') {
             warn('unexpected_a', right);
         }
-        if (left.arity === right.arity && left.arity === 'number') {
+        if (left.id === right.id && left.id === '(number)') {
             left.value %= right.value;
             left.thru = right.thru;
             discard(right);
@@ -3781,7 +3842,7 @@ loop:   for (;;) {
         that.first = left;
         that.second = right;
         return that;
-    });
+    }, 'number');
 
     suffix('++');
     prefix('++');
@@ -3806,7 +3867,7 @@ loop:   for (;;) {
         }
         expression(150);
         return this;
-    });
+    }, 'number');
     prefix('!', function () {
         no_space_only();
         this.first = expected_condition(expression(150));
@@ -3815,11 +3876,11 @@ loop:   for (;;) {
             warn('confusing_a', this);
         }
         return this;
-    });
-    prefix('typeof');
+    }, 'boolean');
+    prefix('typeof', null, 'string');
     prefix('new', function () {
         one_space();
-        var c = expression(160), i, p;
+        var c = expression(160), i, p, v;
         this.first = c;
         if (c.id !== 'function') {
             if (c.identifier) {
@@ -3834,7 +3895,7 @@ loop:   for (;;) {
                         advance('(');
                         if (next_token.id !== ')') {
                             p.second = expression(0);
-                            if (p.second.arity !== 'number' || !p.second.value) {
+                            if (p.second.id !== '(string)' || !p.second.value) {
                                 expected_condition(p.second,  bundle.use_array);
                                 i = false;
                             } else {
@@ -3873,8 +3934,8 @@ loop:   for (;;) {
                     break;
                 default:
                     if (c.id !== 'function') {
-                        i = c.value.substr(0, 1);
-                        if (option.newcap && (i < 'A' || i > 'Z')) {
+                        v = c.value.substr(0, 1);
+                        if (option.newcap && (v < 'A' || v > 'Z')) {
                             warn('constructor_name_a', token);
                         }
                     }
@@ -3949,7 +4010,7 @@ loop:   for (;;) {
                 if (left.value === 'eval' || left.value === 'Function' ||
                         left.value === 'execScript') {
                     warn('evil', left);
-                } else if (p[0] && p[0].arity === 'string' &&
+                } else if (p[0] && p[0].id === '(string)' &&
                         (left.value === 'setTimeout' ||
                         left.value === 'setInterval')) {
                     warn('implied_evil', left);
@@ -3964,7 +4025,7 @@ loop:   for (;;) {
         that.first = left;
         that.second = p;
         return that;
-    }, true);
+    }, '', true);
 
     prefix('(', function () {
         step_in('expression');
@@ -4012,7 +4073,7 @@ loop:   for (;;) {
                     if (xmode !== 'script') {
                         warn('adsafe', that);
                     } else if (adsafe_went || next_token.id !== '(' ||
-                            peek(0).arity !== 'string' ||
+                            peek(0).id !== '(string)' ||
                             peek(0).value !== adsafe_id ||
                             peek(1).id !== ',') {
                         stop('adsafe_a', that, 'go');
@@ -4030,7 +4091,7 @@ loop:   for (;;) {
                 if (banned[name] === true) {
                     warn('adsafe_a', token, name);
                 }
-                if (typeof predefined[left.value] !== 'boolean' ||
+                if (typeof predefined[left.value] !== 'boolean' ||    //// check for writeable
                         next_token.id === '(') {
                     break;
                 }
@@ -4055,7 +4116,7 @@ loop:   for (;;) {
             }
         }
         return that;
-    }, true);
+    }, '', true);
 
     infix('[', 170, function (left, that) {
         no_space_only(prev_token, token);
@@ -4063,11 +4124,11 @@ loop:   for (;;) {
         step_in();
         edge();
         var e = expression(0), s;
-        if (e.arity === 'number') {
+        if (e.id === '(number)') {
             if (left.id === 'arguments') {
                 warn('use_param', left);
             }
-        } else if (e.arity === 'string') {
+        } else if (e.id === '(string)') {
             if (option.safe && (banned[e.value] ||
                     e.value.charAt(0) === '_' || e.value.slice(-1) === '_')) {
                 warn('adsafe_subscript_a', e);
@@ -4094,11 +4155,12 @@ loop:   for (;;) {
         that.first = left;
         that.second = e;
         return that;
-    }, true);
+    }, '', true);
 
     prefix('[', function () {
         this.arity = 'prefix';
         this.first = [];
+        this.type = 'array';
         step_in('array');
         while (next_token.id !== '(end)') {
             while (next_token.id === ',') {
@@ -4131,7 +4193,7 @@ loop:   for (;;) {
     function property_name() {
         var id = optional_identifier(true);
         if (!id) {
-            if (next_token.arity === 'string') {
+            if (next_token.id === '(string)') {
                 id = next_token.value;
                 if (option.safe) {
                     if (banned[id]) {
@@ -4142,7 +4204,7 @@ loop:   for (;;) {
                     }
                 }
                 advance();
-            } else if (next_token.arity === 'number') {
+            } else if (next_token.id === '(number)') {
                 id = next_token.value.toString();
                 advance();
             }
@@ -4167,7 +4229,7 @@ loop:   for (;;) {
             edge();
             id = identifier();
             params.push(token);
-            add_label(id, option.unparam ? 'unparam' : 'parameter');
+            add_label(token, option.unparam ? 'parameter' : 'unparam');
             if (next_token.id === ',') {
                 comma();
             } else {
@@ -4251,45 +4313,61 @@ loop:   for (;;) {
 
 
     function do_function(func, name) {
-        var old_properties = properties,
+        var old_funct      = funct,
             old_option     = option,
-            old_global     = global,
+            old_properties = properties,
             old_scope      = scope;
         funct = {
             '(name)'     : name || '\'' + (anonname || '').replace(nx, sanitize) + '\'',
             '(line)'     : next_token.line,
-            '(context)'  : funct,
+            '(context)'  : old_funct,
             '(breakage)' : 0,
             '(loopage)'  : 0,
             '(scope)'    : scope,
             '(token)'    : func
         };
-        properties  = old_properties && Object.create(old_properties);
-        option      = Object.create(old_option);
-        global      = Object.create(old_global);
-        scope       = Object.create(old_scope);
-        token.funct = funct;
+        properties = old_properties && Object.create(old_properties);
+        option = Object.create(old_option);
+        scope = Object.create(old_scope);
         functions.push(funct);
+        func.name = name;
         if (name) {
-            add_label(name, 'function');
+            add_label(func, 'function', name);
         }
-        func.name = name || '';
+        func.writeable = false;
         func.first = funct['(params)'] = function_params();
+        func.type = 'function';
         one_space();
         func.block = block(false);
         funct['(complexity)'] = complexity(func.block) + 1;
-        funct      = funct['(context)'];
-        properties = old_properties;
+        funct      = old_funct;
         option     = old_option;
-        global     = old_global;
+        properties = old_properties;
         scope      = old_scope;
     }
 
 
+    assignop('=');
+    assignop('+=', '+');
+    assignop('-=', '-');
+    assignop('*=', '*');
+    assignop('/=', '/').nud = function () {
+        stop('slash_equal');
+    };
+    assignop('%=', '%');
+    assignop('&=', '&');
+    assignop('|=', '|');
+    assignop('^=', '^');
+    assignop('<<=', '<<');
+    assignop('>>=', '>>');
+    assignop('>>>=', '>>>');
+
+
     prefix('{', function () {
         var get, i, j, name, p, set, seen = {};
         this.arity = 'prefix';
         this.first = [];
+        this.type = 'object';
         step_in();
         while (next_token.id !== '}') {
             indent.wrap = false;
@@ -4310,7 +4388,8 @@ loop:   for (;;) {
                 if (!i) {
                     stop('missing_property');
                 }
-                do_function(get, '');
+                get.value = '';
+                do_function(get);
                 if (funct['(loopage)']) {
                     warn('function_loop', get);
                 }
@@ -4320,6 +4399,7 @@ loop:   for (;;) {
                 }
                 comma();
                 set = next_token;
+                set.value = '';
                 spaces();
                 edge();
                 advance('set');
@@ -4328,7 +4408,7 @@ loop:   for (;;) {
                 if (i !== j) {
                     stop('expected_a_b', token, i, j || next_token.value);
                 }
-                do_function(set, '');
+                do_function(set);
                 p = set.first;
                 if (!p || p.length !== 1) {
                     stop('parameter_set_a', set, 'value');
@@ -4403,7 +4483,7 @@ loop:   for (;;) {
 
         if (funct['(onevar)'] && option.onevar) {
             warn('combine_var');
-        } else if (!funct['(global)']) {
+        } else if (funct !== global_funct) {
             funct['(onevar)'] = true;
         }
         this.arity = 'statement';
@@ -4412,10 +4492,7 @@ loop:   for (;;) {
         for (;;) {
             name = next_token;
             id = identifier();
-            if (funct['(global)'] && predefined[id] === false) {
-                warn('redefinition_a', token, id);
-            }
-            add_label(id, 'error');
+            add_label(name, 'becoming');
 
             if (next_token.id === '=') {
                 assign = next_token;
@@ -4432,10 +4509,15 @@ loop:   for (;;) {
                 assign.second = expression(0);
                 assign.arity = 'infix';
                 this.first.push(assign);
+                if (assign.second.type) {
+                    name.type = assign.second.type;
+                }
             } else {
                 this.first.push(name);
             }
-            funct[id] = 'unused';
+            if (funct[id] === 'becoming') {
+                funct[id] = 'unused';
+            }
             if (next_token.id !== ',') {
                 break;
             }
@@ -4443,14 +4525,14 @@ loop:   for (;;) {
             indent.wrap = false;
             if (var_mode && next_token.line === token.line &&
                     this.first.length === 1) {
-                var_mode = false;
+                var_mode = null;
                 indent.open = false;
                 indent.at -= option.indent;
             }
             spaces();
             edge();
         }
-        var_mode = false;
+        var_mode = null;
         step_out();
         return this;
     });
@@ -4460,12 +4542,10 @@ loop:   for (;;) {
         if (in_block) {
             warn('function_block', token);
         }
-        var i = identifier();
-        if (i) {
-            add_label(i, 'unction');
-            no_space();
-        }
-        do_function(this, i, true);
+        var name = next_token, id = identifier();
+        add_label(name, 'unction');
+        no_space();
+        do_function(this, id);
         if (next_token.id === '(' && next_token.line === token.line) {
             stop('function_statement');
         }
@@ -4475,11 +4555,13 @@ loop:   for (;;) {
 
     prefix('function', function () {
         one_space();
-        var i = optional_identifier();
-        if (i) {
+        var id = optional_identifier();
+        if (id) {
             no_space();
+        } else {
+            id = '';
         }
-        do_function(this, i);
+        do_function(this, id);
         if (funct['(loopage)']) {
             warn('function_loop');
         }
@@ -4548,7 +4630,7 @@ loop:   for (;;) {
             if (!next_token.identifier) {
                 warn('expected_identifier_a', next_token);
             } else {
-                add_label(exception_variable, 'exception');
+                add_label(next_token, 'exception');
             }
             advance();
             no_space();
@@ -4875,7 +4957,7 @@ loop:   for (;;) {
             one_space_only();
             if (funct[label] !== 'label') {
                 warn('not_a_label', next_token);
-            } else if (scope[label] !== funct) {
+            } else if (scope[label].funct !== funct) {
                 warn('not_a_scope', next_token);
             }
             this.first = next_token;
@@ -4897,7 +4979,7 @@ loop:   for (;;) {
             one_space_only();
             if (funct[label] !== 'label') {
                 warn('not_a_label', next_token);
-            } else if (scope[label] !== funct) {
+            } else if (scope[label].funct !== funct) {
                 warn('not_a_scope', next_token);
             }
             this.first = next_token;
@@ -4962,7 +5044,7 @@ loop:   for (;;) {
                         warn('unexpected_a', next_token);
                         comma();
                     }
-                    if (next_token.arity !== 'string') {
+                    if (next_token.id !== '(string)') {
                         warn('expected_string_a');
                     }
                     if (object[next_token.value] === true) {
@@ -5051,7 +5133,7 @@ loop:   for (;;) {
             advance('-');
             no_space_only();
         }
-        if (next_token.arity === 'number') {
+        if (next_token.id === '(number)') {
             advance('(number)');
             return true;
         }
@@ -5059,7 +5141,7 @@ loop:   for (;;) {
 
 
     function css_string() {
-        if (next_token.arity === 'string') {
+        if (next_token.id === '(string)') {
             advance();
             return true;
         }
@@ -5078,7 +5160,7 @@ loop:   for (;;) {
                         comma();
                     }
                     number = next_token.value;
-                    if (next_token.arity !== 'number' || number < 0) {
+                    if (next_token.id !== '(string)' || number < 0) {
                         warn('expected_positive_a', next_token);
                         advance();
                     } else {
@@ -5098,7 +5180,7 @@ loop:   for (;;) {
                 if (value === 'rgba') {
                     comma();
                     number = +next_token.value;
-                    if (next_token.arity !== 'number' || number < 0 || number > 1) {
+                    if (next_token.id !== '(string)' || number < 0 || number > 1) {
                         warn('expected_fraction_a', next_token);
                     }
                     advance();
@@ -5126,9 +5208,9 @@ loop:   for (;;) {
             advance('-');
             no_space_only();
         }
-        if (next_token.arity === 'number') {
+        if (next_token.id === '(number)') {
             advance();
-            if (next_token.arity !== 'string' &&
+            if (next_token.id !== '(string)' &&
                     css_lengthData[next_token.value] === true) {
                 no_space_only();
                 advance();
@@ -5146,9 +5228,9 @@ loop:   for (;;) {
             advance('-');
             no_space_only();
         }
-        if (next_token.arity === 'number') {
+        if (next_token.id === '(number)') {
             advance();
-            if (next_token.arity !== 'string' &&
+            if (next_token.id !== '(string)' &&
                     css_lengthData[next_token.value] === true) {
                 no_space_only();
                 advance();
@@ -5220,7 +5302,7 @@ loop:   for (;;) {
             advance();
             if (next_token.id === ',') {
                 comma();
-                if (next_token.arity !== 'string') {
+                if (next_token.id !== '(string)') {
                     warn('expected_string_a');
                 }
                 advance();
@@ -5237,14 +5319,14 @@ loop:   for (;;) {
             advance();
             if (next_token.id === ',') {
                 comma();
-                if (next_token.arity !== 'string') {
+                if (next_token.id !== '(string)') {
                     warn('expected_string_a');
                 }
                 advance();
             }
             if (next_token.id === ',') {
                 comma();
-                if (next_token.arity !== 'string') {
+                if (next_token.id !== '(string)') {
                     warn('expected_string_a');
                 }
                 advance();
@@ -5588,7 +5670,7 @@ loop:   for (;;) {
             }
             vi = v[i];
             i += 1;
-            if (vi === true) {
+            if (typeof vi === 'boolean') {
                 break;
             } else if (typeof vi === 'number') {
                 n = vi;
@@ -5631,7 +5713,7 @@ loop:   for (;;) {
     }
 
     function style_child() {
-        if (next_token.arity === 'number') {
+        if (next_token.id === '(number)') {
             advance();
             if (next_token.value === 'n' && next_token.identifier) {
                 no_space_only();
@@ -5791,7 +5873,7 @@ loop:   for (;;) {
                         next_token.id === '*=' ||
                         next_token.id === '^=') {
                     advance();
-                    if (next_token.arity !== 'string') {
+                    if (next_token.id !== '(string)') {
                         warn('expected_string_a');
                     }
                     advance();
@@ -5901,7 +5983,6 @@ loop:   for (;;) {
             }
         }
         option.browser = true;
-        assume();
     }
 
     function do_attribute(a, v) {
@@ -6236,8 +6317,8 @@ loop:   for (;;) {
                             if (!next_token.identifier &&
                                     next_token.id !== '"' &&
                                     next_token.id !== '\'' &&
-                                    next_token.arity !== 'string' &&
-                                    next_token.arity !== 'number' &&
+                                    next_token.id !== '(string)' &&
+                                    next_token.id !== '(string)' &&
                                     next_token.id !== '(color)') {
                                 warn('expected_attribute_value_a', token, attribute);
                             }
@@ -6330,14 +6411,15 @@ loop:   for (;;) {
 
 // The actual JSLINT function itself.
 
-    var itself = function (the_source, the_option) {
-        var i, keys, predef, tree;
+    itself = function (the_source, the_option) {
+        var i, predef, tree;
         JSLINT.comments = [];
         JSLINT.errors = [];
         JSLINT.tree = '';
         begin = older_token = prev_token = token = next_token =
             Object.create(syntax['(begin)']);
-        predefined = Object.create(standard);
+        predefined = {};
+        add_to_predefined(standard);
         if (the_option) {
             option = Object.create(the_option);
             predef = option.predef;
@@ -6347,41 +6429,10 @@ loop:   for (;;) {
                         predefined[predef[i]] = true;
                     }
                 } else if (typeof predef === 'object') {
-                    keys = Object.keys(predef);
-                    for (i = 0; i < keys.length; i += 1) {
-                        predefined[keys[i]] = !!predef[keys];
-                    }
+                    add_to_predefined(predef);
                 }
             }
-            if (option.adsafe) {
-                option.safe = true;
-            }
-            if (option.safe) {
-                option.browser     =
-                    option['continue'] =
-                    option.css     =
-                    option.debug   =
-                    option.devel   =
-                    option.evil    =
-                    option.forin   =
-                    option.on      =
-                    option.rhino   =
-                    option.sub     =
-                    option.widget  =
-                    option.windows = false;
-
-                option.nomen       =
-                    option.strict  =
-                    option.undef   = true;
-
-                predefined.Date         =
-                    predefined['eval']  =
-                    predefined.Function =
-                    predefined.Object   = null;
-
-                predefined.ADSAFE  =
-                    predefined.lib = false;
-            }
+            do_safe();
         } else {
             option = {};
         }
@@ -6401,11 +6452,8 @@ loop:   for (;;) {
         for (i = 0; i < option.indent; i += 1) {
             tab += ' ';
         }
-        global = Object.create(predefined);
-        scope = global;
-        funct = {
-            '(global)': true,
-            '(name)': '(global)',
+        global_scope = scope = {};
+        global_funct = funct = {
             '(scope)': scope,
             '(breakage)': 0,
             '(loopage)': 0
@@ -6414,28 +6462,28 @@ loop:   for (;;) {
 
         comments_off = false;
         ids = {};
-        implied = {};
         in_block = false;
-        indent = false;
+        indent = null;
         json_mode = false;
         lookahead = [];
         member = {};
+        node_js = false;
         properties = null;
         prereg = true;
         src = false;
         stack = null;
         strict_mode = false;
         urls = [];
-        var_mode = false;
+        var_mode = null;
         warnings = 0;
-        xmode = false;
+        xmode = '';
         lex.init(the_source);
 
         assume();
 
         try {
             advance();
-            if (next_token.arity === 'number') {
+            if (next_token.id === '(number)') {
                 stop('unexpected_a');
             } else if (next_token.value.charAt(0) === '<') {
                 html();
@@ -6462,7 +6510,7 @@ loop:   for (;;) {
                         stop('css');
                     }
                     advance();
-                    if (next_token.arity !== 'string' &&
+                    if (next_token.id !== '(string)' &&
                             next_token.value !== 'UTF-8') {
                         stop('css');
                     }
@@ -6482,13 +6530,9 @@ loop:   for (;;) {
 // file may be depending on semicolon insertion on its last line.
 
                     step_in(1);
-                    if (next_token.id === ';') {
+                    if (next_token.id === ';' && !node_js) {
                         semicolon();
                     }
-                    if (next_token.value === 'use strict') {
-                        warn('function_strict');
-                        use_strict();
-                    }
                     adsafe_top = true;
                     tree = statements();
                     begin.first = tree;
@@ -6499,7 +6543,7 @@ loop:   for (;;) {
                             aint(tree[0].first.first, 'value', 'ADSAFE') ||
                             aint(tree[0].first.second, 'value', 'lib') ||
                             tree[0].second.length !== 2 ||
-                            tree[0].second[0].arity !== 'string' ||
+                            tree[0].second[0].id !== '(string)' ||
                             aint(tree[0].second[1], 'id', 'function'))) {
                         stop('adsafe_lib');
                     }
@@ -6530,12 +6574,12 @@ loop:   for (;;) {
             function_data,
             globals,
             i,
-            implieds = [],
             j,
             kind,
             members = [],
             name,
             the_function,
+            undef = [],
             unused = [];
         if (itself.errors.length) {
             data.errors = itself.errors;
@@ -6545,23 +6589,11 @@ loop:   for (;;) {
             data.json = true;
         }
 
-        for (name in implied) {
-            if (Object.prototype.hasOwnProperty.call(implied, name)) {
-                implieds.push({
-                    name: name,
-                    line: implied[name]
-                });
-            }
-        }
-        if (implieds.length > 0) {
-            data.implieds = implieds;
-        }
-
         if (urls.length > 0) {
             data.urls = urls;
         }
 
-        globals = Object.keys(functions[0]).filter(function (value) {
+        globals = Object.keys(global_scope).filter(function (value) {
             return value.charAt(0) !== '(' ? value : undefined;
         });
         if (globals.length > 0) {
@@ -6580,8 +6612,6 @@ loop:   for (;;) {
                         kind = the_function[name];
                         if (kind === 'unction' || kind === 'unparam') {
                             kind = 'unused';
-                        } else if (typeof kind === 'boolean') {
-                            kind = 'global';
                         }
                         if (Array.isArray(function_data[kind])) {
                             function_data[kind].push(name);
@@ -6591,6 +6621,12 @@ loop:   for (;;) {
                                     line: the_function['(line)'],
                                     'function': the_function['(name)']
                                 });
+                            } else if (kind === 'undef') {
+                                undef.push({
+                                    name: name,
+                                    line: the_function['(line)'],
+                                    'function': the_function['(name)']
+                                });
                             }
                         }
                     }
@@ -6611,6 +6647,9 @@ loop:   for (;;) {
         if (unused.length > 0) {
             data.unused = unused;
         }
+        if (undef.length > 0) {
+            data.undef = undef;
+        }
 
         members = [];
         for (name in member) {
@@ -6625,9 +6664,8 @@ loop:   for (;;) {
 
 
     itself.report = function (errors_only) {
-        var data = itself.data();
-
-        var err, evidence, i, j, key, keys, length, mem = '', name, names,
+        var data = itself.data(),
+            err, evidence, i, j, key, keys, length, mem = '', name, names,
             output = [], snippets, the_function, warning;
 
         function detail(h, value) {
@@ -6647,7 +6685,7 @@ loop:   for (;;) {
             }
         }
 
-        if (data.errors || data.implieds || data.unused) {
+        if (data.errors || data.unused || data.undef) {
             err = true;
             output.push('<div id=errors><i>Error:</i>');
             if (data.errors) {
@@ -6665,15 +6703,15 @@ loop:   for (;;) {
                 }
             }
 
-            if (data.implieds) {
+            if (data.undef) {
                 snippets = [];
-                for (i = 0; i < data.implieds.length; i += 1) {
-                    snippets[i] = '<code>' + data.implieds[i].name + '</code>&nbsp;<i>' +
-                        data.implieds[i].line + '</i>';
+                for (i = 0; i < data.undef.length; i += 1) {
+                    snippets[i] = '<code><u>' + data.undef[i].name + '</u></code>&nbsp;<i>' +
+                        data.undef[i].line + ' </i> <small>' +
+                        data.undef[i]['function'] + '</small>';
                 }
-                output.push('<p><i>Implied global:</i> ' + snippets.join(', ') + '</p>');
+                output.push('<p><i>Undefined variable:</i> ' + snippets.join(', ') + '</p>');
             }
-
             if (data.unused) {
                 snippets = [];
                 for (i = 0; i < data.unused.length; i += 1) {
@@ -6719,6 +6757,7 @@ loop:   for (;;) {
                 output.push('<br><div class=function><i>' + the_function.line +
                     '</i> ' + the_function.name.entityify() +
                     '(' + names.join(', ') + ')</div>');
+                detail('<big><b>Undefined</b></big>', the_function.undef);
                 detail('<big><b>Unused</b></big>', the_function.unused);
                 detail('Closure', the_function.closure);
                 detail('Variable', the_function['var']);
@@ -6762,7 +6801,7 @@ loop:   for (;;) {
     };
     itself.jslint = itself;
 
-    itself.edition = '2011-05-10';
+    itself.edition = '2011-06-07';
 
     return itself;
 
-- 
GitLab