refactor(jshint): don't assume browser-only globals

Fixes #13442
Closes #14345
This commit is contained in:
Michał Gołębiowski
2016-03-30 14:29:59 +02:00
parent fad6c7c661
commit ddad26402b
36 changed files with 2698 additions and 4567 deletions
+8 -3
View File
@@ -1,19 +1,24 @@
{
"bitwise": true,
"esversion": 6,
"immed": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nonew": true,
"trailing": true,
"maxlen": 200,
"boss": true,
"eqnull": true,
"expr": true,
"globalstrict": true,
"laxbreak": true,
"loopfunc": true,
"strict": "global",
"sub": true,
"undef": true,
"indent": 2
"indent": 2,
"globals": {
"ArrayBuffer": false,
"Uint8Array": false
}
}
+4 -1
View File
@@ -19,9 +19,12 @@
"dump": false,
/* e2e */
"protractor": false,
"browser": false,
"element": false,
"by": false,
"$": false,
"$$": false,
/* testabilityPatch / matchers */
"inject": false,
@@ -39,4 +42,4 @@
"browserTrigger": false,
"jqLiteCacheSize": false
}
}
}
+44 -5
View File
@@ -1,5 +1,9 @@
"use strict";
var fs = require('fs');
var _ = require('lodash');
var stripJsonComments = require('strip-json-comments');
var gulp = require('gulp');
var log = require('gulp-util').log;
var concat = require('gulp-concat');
@@ -25,6 +29,23 @@ var ignoredFiles = '!src/angular.bind.js';
var assets = 'app/assets/**/*';
var getJshintConfig = function(filepath) {
return JSON.parse(stripJsonComments(fs.readFileSync(filepath, {encoding: 'utf-8'})));
};
var getMergedJshintConfig = function(filepath) {
// "extends" doesn't work in configuration passed by an object, we need to do the extending ourselves.
var config = getJshintConfig(filepath);
var baseConfig = getJshintConfig('../.jshintrc-base');
_.merge(config, baseConfig);
delete config.extends;
// Examples don't run in strict mode; accept that for now.
config.strict = false;
return config;
};
var copyComponent = function(component, pattern, sourceFolder, packageFile) {
pattern = pattern || '/**/*';
sourceFolder = sourceFolder || bowerFolder;
@@ -90,17 +111,35 @@ gulp.task('assets', ['bower'], function() {
gulp.task('doc-gen', ['bower'], function() {
var dgeni = new Dgeni([require('./config')]);
return dgeni.generate().catch(function(error) {
return dgeni.generate().catch(function() {
process.exit(1);
});
});
// JSHint the example and protractor test files
gulp.task('jshint', ['doc-gen'], function() {
gulp.src([outputFolder + '/ptore2e/**/*.js', outputFolder + '/examples/**/*.js'])
.pipe(jshint())
.pipe(jshint.reporter('jshint-stylish'))
.pipe(jshint.reporter('fail'));
var examplesConfig = getMergedJshintConfig('../docs/app/test/.jshintrc');
// Some tests use `alert` which is not assumed to be available even with `"browser": true`.
examplesConfig.globals.alert = false;
var protractorConfig = getMergedJshintConfig('../docs/app/e2e/.jshintrc');
return merge(
gulp.src([
outputFolder + '/examples/**/*.js',
'!' + outputFolder + '/examples/**/protractor.js',
])
.pipe(jshint(examplesConfig))
.pipe(jshint.reporter('jshint-stylish'))
.pipe(jshint.reporter('fail')),
gulp.src([
outputFolder + '/ptore2e/**/*.js',
outputFolder + '/examples/**/protractor.js',
])
.pipe(jshint(protractorConfig))
.pipe(jshint.reporter('jshint-stylish'))
.pipe(jshint.reporter('fail'))
);
});
+192 -958
View File
File diff suppressed because it is too large Load Diff
+2363 -3529
View File
File diff suppressed because it is too large Load Diff
+6 -4
View File
@@ -39,7 +39,7 @@
"grunt-contrib-compress": "~0.12.0",
"grunt-contrib-connect": "~0.8.0",
"grunt-contrib-copy": "~0.6.0",
"grunt-contrib-jshint": "~0.10.0",
"grunt-contrib-jshint": "^1.0.0",
"grunt-ddescribe-iit": "~0.0.1",
"grunt-jasmine-node": "git://github.com/vojtajina/grunt-jasmine-node.git#fix-grunt-exit-code",
"grunt-jscs": "^2.1.0",
@@ -48,7 +48,7 @@
"gulp": "~3.8.0",
"gulp-concat": "^2.4.1",
"gulp-foreach": "0.0.1",
"gulp-jshint": "~1.4.2",
"gulp-jshint": "^2.0.0",
"gulp-rename": "^1.2.0",
"gulp-sourcemaps": "^1.2.2",
"gulp-uglify": "^1.0.1",
@@ -56,7 +56,8 @@
"jasmine-core": "^2.4.0",
"jasmine-node": "^2.0.0",
"jasmine-reporters": "~1.0.1",
"jshint-stylish": "~1.0.0",
"jshint": "^2.9.1",
"jshint-stylish": "^2.1.0",
"karma": "^0.13.19",
"karma-browserstack-launcher": "^0.1.8",
"karma-chrome-launcher": "^0.2.2",
@@ -80,7 +81,8 @@
"semver": "~4.0.3",
"shelljs": "~0.3.0",
"sorted-object": "^1.0.0",
"stringmap": "^0.2.2"
"stringmap": "^0.2.2",
"strip-json-comments": "^2.0.1"
},
"licenses": [
{
+2 -1
View File
@@ -1,9 +1,10 @@
{
"extends": "../.jshintrc-base",
"browser": true,
"eqeqeq": true,
"eqnull": true,
"globals": {
"window": false,
/* auto/injector.js */
"createInjector": false,
+6 -6
View File
@@ -169,7 +169,7 @@ var
* documentMode is an IE-only property
* http://msdn.microsoft.com/en-us/library/ie/cc196988(v=vs.85).aspx
*/
msie = document.documentMode;
msie = window.document.documentMode;
/**
@@ -1027,8 +1027,8 @@ var csp = function() {
if (!isDefined(csp.rules)) {
var ngCspElement = (document.querySelector('[ng-csp]') ||
document.querySelector('[data-ng-csp]'));
var ngCspElement = (window.document.querySelector('[ng-csp]') ||
window.document.querySelector('[data-ng-csp]'));
if (ngCspElement) {
var ngCspAttribute = ngCspElement.getAttribute('ng-csp') ||
@@ -1103,7 +1103,7 @@ var jq = function() {
var i, ii = ngAttrPrefixes.length, prefix, name;
for (i = 0; i < ii; ++i) {
prefix = ngAttrPrefixes[i];
if (el = document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
if (el = window.document.querySelector('[' + prefix.replace(':', '\\:') + 'jq]')) {
name = el.getAttribute(prefix + 'jq');
break;
}
@@ -1168,7 +1168,7 @@ function toJsonReplacer(key, value) {
val = undefined;
} else if (isWindow(value)) {
val = '$WINDOW';
} else if (value && document === value) {
} else if (value && window.document === value) {
val = '$DOCUMENT';
} else if (isScope(value)) {
val = '$SCOPE';
@@ -1620,7 +1620,7 @@ function bootstrap(element, modules, config) {
element = jqLite(element);
if (element.injector()) {
var tag = (element[0] === document) ? 'document' : startingTag(element);
var tag = (element[0] === window.document) ? 'document' : startingTag(element);
//Encode angle brackets to prevent input from being sanitized to empty string #8683
throw ngMinErr(
'btstrpd',
+1 -1
View File
@@ -3,4 +3,4 @@
* (c) 2010-2016 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document, undefined) {
(function(window) {
+3 -3
View File
@@ -1,5 +1,5 @@
jqLite(document).ready(function() {
angularInit(document, bootstrap);
jqLite(window.document).ready(function() {
angularInit(window.document, bootstrap);
});
})(window, document);
})(window);
+4 -4
View File
@@ -232,7 +232,7 @@ function jqLiteBuildFragment(html, context) {
}
function jqLiteParseHTML(html, context) {
context = context || document;
context = context || window.document;
var parsed;
if ((parsed = SINGLE_TAG_REGEXP.exec(html))) {
@@ -258,7 +258,7 @@ function jqLiteWrapNode(node, wrapper) {
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
var jqLiteContains = Node.prototype.contains || function(arg) {
var jqLiteContains = window.Node.prototype.contains || function(arg) {
// jshint bitwise: false
return !!(this.compareDocumentPosition(arg) & 16);
// jshint bitwise: true
@@ -530,8 +530,8 @@ var JQLitePrototype = JQLite.prototype = {
}
// check if document is already loaded
if (document.readyState === 'complete') {
setTimeout(trigger);
if (window.document.readyState === 'complete') {
window.setTimeout(trigger);
} else {
this.on('DOMContentLoaded', trigger); // works for modern browsers and IE9
// we can not use jqLite since we are not done loading and jQuery could be loaded later.
+1 -1
View File
@@ -3,4 +3,4 @@
* (c) 2010-2016 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {
(function(window, angular) {
+6 -4
View File
@@ -1274,7 +1274,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
$controller, $rootScope, $sce, $animate, $$sanitizeUri) {
var SIMPLE_ATTR_NAME = /^\w/;
var specialAttrHolder = document.createElement('div');
var specialAttrHolder = window.document.createElement('div');
@@ -1605,7 +1605,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
if (debugInfoEnabled) {
content = ' ' + (directiveName || '') + ': ' + (comment || '') + ' ';
}
return document.createComment(content);
return window.document.createComment(content);
};
return compile;
@@ -2308,7 +2308,9 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
replaceDirective = directive;
}
/* jshint -W021 */
nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), $compileNode,
/* jshint +W021 */
templateAttrs, jqCollection, hasTranscludeDirective && childTranscludeFn, preLinkFns, postLinkFns, {
controllerDirectives: controllerDirectives,
newScopeDirective: (newScopeDirective !== directive) && newScopeDirective,
@@ -2914,7 +2916,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
switch (type) {
case 'svg':
case 'math':
var wrapper = document.createElement('div');
var wrapper = window.document.createElement('div');
wrapper.innerHTML = '<' + type + '>' + template + '</' + type + '>';
return wrapper.childNodes[0].childNodes;
default:
@@ -3058,7 +3060,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
// - remove them from the DOM
// - allow them to still be traversed with .nextSibling
// - allow a single fragment.qSA to fetch all elements being removed
var fragment = document.createDocumentFragment();
var fragment = window.document.createDocumentFragment();
for (i = 0; i < removeCount; i++) {
fragment.appendChild(elementsToRemove[i]);
}
+1 -1
View File
@@ -292,7 +292,7 @@ var ngIncludeFillContentDirective = ['$compile',
// support innerHTML, so detect this here and try to generate the contents
// specially.
$element.empty();
$compile(jqLiteBuildFragment(ctrl.template, document).childNodes)(scope,
$compile(jqLiteBuildFragment(ctrl.template, window.document).childNodes)(scope,
function namespaceAdaptedClone(clone) {
$element.append(clone);
}, {futureParentElement: $element});
+2 -2
View File
@@ -406,8 +406,8 @@ var ngOptionsDirective = ['$compile', '$parse', function($compile, $parse) {
// we can't just jqLite('<option>') since jqLite is not smart enough
// to create it in <select> and IE barfs otherwise.
var optionTemplate = document.createElement('option'),
optGroupTemplate = document.createElement('optgroup');
var optionTemplate = window.document.createElement('option'),
optGroupTemplate = window.document.createElement('optgroup');
function ngOptionsPostLink(scope, selectElement, attr, ctrls) {
+1 -1
View File
@@ -34,7 +34,7 @@ var SelectController =
//
// We can't just jqLite('<option>') since jqLite is not smart enough
// to create it in <select> and IE barfs otherwise.
self.unknownOption = jqLite(document.createElement('option'));
self.unknownOption = jqLite(window.document.createElement('option'));
self.renderUnknownOption = function(val) {
var unknownVal = '? ' + hashKey(val) + ' ?';
self.unknownOption.val(unknownVal);
+1 -1
View File
@@ -6,7 +6,7 @@
// doesn't know about mocked locations and resolves URLs to the real document - which is
// exactly the behavior needed here. There is little value is mocking these out for this
// service.
var urlParsingNode = document.createElement("a");
var urlParsingNode = window.document.createElement("a");
var originUrl = urlResolve(window.location.href);
+2 -1
View File
@@ -2,8 +2,9 @@
"extends": "../../.jshintrc-base",
"maxlen": false, /* ngAnimate docs contain wide tables */
"newcap": false,
"browser": true,
"globals": {
"window": false,
"angular": false,
"noop": false,
+1 -1
View File
@@ -174,7 +174,7 @@ var $$AnimateQueueProvider = ['$animateProvider', function($animateProvider) {
}
// IE9-11 has no method "contains" in SVG element and in Node.prototype. Bug #10259.
var contains = Node.prototype.contains || function(arg) {
var contains = window.Node.prototype.contains || function(arg) {
// jshint bitwise: false
return this === arg || !!(this.compareDocumentPosition(arg) & 16);
// jshint bitwise: true
+3 -2
View File
@@ -1,7 +1,8 @@
{
"extends": "../../.jshintrc-base",
"browser": true,
"globals": {
"window": false,
"angular": false
}
}
}
+3 -2
View File
@@ -3,9 +3,10 @@
"bitwise": false, /* locale files use bitwise operators */
"maxlen": false, /* locale files are generated from a 3rd party library that has long lines */
"eqeqeq": false,
"browser": true,
"globals": {
"window": false,
"angular": false
},
"-W041": false
}
}
+2 -1
View File
@@ -1,7 +1,8 @@
{
"extends": "../../.jshintrc-base",
"browser": true,
"globals": {
"window": false,
"angular": false,
"goog": false // see src/module_closure.prefix
}
+3 -2
View File
@@ -1,9 +1,10 @@
{
"extends": "../../.jshintrc-base",
"browser": true,
"globals": {
"window": false,
"angular": false,
"expect": false,
"jQuery": false
}
}
}
+3 -2
View File
@@ -1,7 +1,8 @@
{
"extends": "../../.jshintrc-base",
"browser": true,
"globals": {
"window": false,
"angular": false
}
}
}
+3 -2
View File
@@ -1,8 +1,9 @@
{
"extends": "../../.jshintrc-base",
"browser": true,
"globals": {
"window": false,
"angular": false,
"ngRouteModule": false
}
}
}
+3 -2
View File
@@ -1,8 +1,9 @@
{
"extends": "../../.jshintrc-base",
"browser": true,
"globals": {
"window": false,
"angular": false,
"htmlSanitizeWriter": false
}
}
}
+2 -2
View File
@@ -344,7 +344,7 @@ function htmlParser(html, handler) {
mXSSAttempts--;
// strip custom-namespaced attributes on IE<=11
if (document.documentMode <= 11) {
if (window.document.documentMode) {
stripCustomNsAttrs(inertBodyElement);
}
html = inertBodyElement.innerHTML; //trigger mXSS
@@ -484,7 +484,7 @@ function htmlSanitizeWriter(buf, uriValidator) {
* @param node Root element to process
*/
function stripCustomNsAttrs(node) {
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.nodeType === window.Node.ELEMENT_NODE) {
var attrs = node.attributes;
for (var i = 0, l = attrs.length; i < l; i++) {
var attrNode = attrs[i];
+3 -2
View File
@@ -1,7 +1,8 @@
{
"extends": "../../.jshintrc-base",
"browser": true,
"globals": {
"window": false,
"angular": false,
"includes": false,
"asyncForEach": false,
@@ -19,4 +20,4 @@
"$runner": false,
"callerFile": false
}
}
}
+1 -1
View File
@@ -104,7 +104,7 @@ angular.scenario.matcher = angular.scenario.matcher || function(name, fn) {
*/
angular.scenario.setUpAndRun = function(config) {
var href = window.location.href;
var body = _jQuery(document.body);
var body = _jQuery(window.document.body);
var output = [];
var objModel = new angular.scenario.ObjectModel($runner);
+5 -5
View File
@@ -5,7 +5,7 @@
(function(previousOnLoad) {
var prefix = (function() {
var filename = /(.*\/)angular-bootstrap.js(#(.*))?/;
var scripts = document.getElementsByTagName("script");
var scripts = window.document.getElementsByTagName("script");
for (var j = 0; j < scripts.length; j++) {
var src = scripts[j].src;
if (src && src.match(filename)) {
@@ -16,11 +16,11 @@
})();
function addScript(path) {
document.write('<script type="text/javascript" src="' + prefix + path + '"></script>');
window.document.write('<script type="text/javascript" src="' + prefix + path + '"></script>');
}
function addCSS(path) {
document.write('<link rel="stylesheet" type="text/css" href="' + prefix + path + '"/>');
window.document.write('<link rel="stylesheet" type="text/css" href="' + prefix + path + '"/>');
}
window.onload = function() {
@@ -32,7 +32,7 @@
addCSS("../../css/angular-scenario.css");
addScript("../../lib/jquery/jquery.js");
document.write(
window.document.write(
'<script type="text/javascript">' +
'var _jQuery = jQuery.noConflict(true);' +
'</script>'
@@ -54,7 +54,7 @@
addScript("output/Xml.js");
// Create the runner (which also sets up the global API)
document.write(
window.document.write(
'<script type="text/javascript">' +
' var $runner = new angular.scenario.Runner(window);' +
'</script>');
+1 -1
View File
@@ -3,5 +3,5 @@
* (c) 2010-2016 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document){
(function(window){
var _jQuery = window.jQuery.noConflict(true);
+3 -3
View File
@@ -2,7 +2,7 @@ bindJQuery();
publishExternalAPI(angular);
var $runner = new angular.scenario.Runner(window),
scripts = document.getElementsByTagName('script'),
scripts = window.document.getElementsByTagName('script'),
script = scripts[scripts.length - 1],
config = {};
@@ -14,9 +14,9 @@ angular.forEach(script.attributes, function(attr) {
});
if (config.autotest) {
JQLite(document).ready(function() {
JQLite(window.document).ready(function() {
angular.scenario.setUpAndRun(config);
});
}
})(window, document);
})(window);
+8 -8
View File
@@ -61,7 +61,7 @@
evnt = new TransitionEvent(eventType, eventData);
}
catch (e) {
evnt = document.createEvent('TransitionEvent');
evnt = window.document.createEvent('TransitionEvent');
evnt.initTransitionEvent(eventType, null, null, null, eventData.elapsedTime || 0);
}
}
@@ -74,14 +74,14 @@
evnt = new AnimationEvent(eventType, eventData);
}
catch (e) {
evnt = document.createEvent('AnimationEvent');
evnt = window.document.createEvent('AnimationEvent');
evnt.initAnimationEvent(eventType, null, null, null, eventData.elapsedTime || 0);
}
}
} else if (/touch/.test(eventType) && supportsTouchEvents()) {
evnt = createTouchEvent(element, eventType, x, y);
} else {
evnt = document.createEvent('MouseEvents');
evnt = window.document.createEvent('MouseEvents');
x = x || 0;
y = y || 0;
evnt.initMouseEvent(eventType, true, true, window, 0, x, y, x, y, pressed('ctrl'),
@@ -120,12 +120,12 @@
if ('_cached' in supportsTouchEvents) {
return supportsTouchEvents._cached;
}
if (!document.createTouch || !document.createTouchList) {
if (!window.document.createTouch || !window.document.createTouchList) {
supportsTouchEvents._cached = false;
return false;
}
try {
document.createEvent('TouchEvent');
window.document.createEvent('TouchEvent');
} catch (e) {
supportsTouchEvents._cached = false;
return false;
@@ -135,12 +135,12 @@
}
function createTouchEvent(element, eventType, x, y) {
var evnt = new Event(eventType);
var evnt = new window.Event(eventType);
x = x || 0;
y = y || 0;
var touch = document.createTouch(window, element, Date.now(), x, y, x, y);
var touches = document.createTouchList(touch);
var touch = window.document.createTouch(window, element, Date.now(), x, y, x, y);
var touches = window.document.createTouchList(touch);
evnt.touches = touches;
+1 -1
View File
@@ -199,7 +199,7 @@ angular.scenario.dsl('binding', function() {
*/
angular.scenario.dsl('input', function() {
var chain = {};
var supportInputEvent = 'oninput' in document.createElement('div') && !(msie && msie <= 11);
var supportInputEvent = 'oninput' in window.document.createElement('div') && !msie;
chain.enter = function(value, event) {
return this.addFutureAction("input '" + this.name + "' enter '" + value + "'",
+3 -2
View File
@@ -1,8 +1,9 @@
{
"extends": "../../.jshintrc-base",
"browser": true,
"globals": {
"window": false,
"angular": false,
"ngTouch": false
}
}
}
+3 -2
View File
@@ -1,3 +1,4 @@
// When runnint the modules test, then the page should not be bootstrapped.
window.name = "NG_DEFER_BOOTSTRAP!";
'use strict';
// When running the modules test, then the page should not be bootstrapped.
window.name = "NG_DEFER_BOOTSTRAP!";