Compare commits

...

12 Commits

Author SHA1 Message Date
Raphael Jamet 7e6155a6f1 refactor($templateRequest): Remove useless dependencies in tests 2015-07-01 12:16:14 -07:00
Raphael Jamet 0f034444c3 docs($templateRequest): update the description with caching changes
The previous changes to $templateRequest were not documented, they now are.
2015-07-01 12:16:03 -07:00
Raphael Jamet 74ecea9f2d refactor($templateRequest): move $sce checks and trust the cache
Move all the calls to $sce.getTrustedUrl inside $templateRequest, and
also trust the contents of the cache. This allows prefetching templates
and to bypass the checks on things where they make no sense, like
templates specified in script tags.

Closes #12219
Closes #12220
Closes #12240
2015-07-01 12:15:57 -07:00
Peter Bacon Darwin 8d5c08c6b8 chore(doc-gen): update to dgeni-packages 0.10.17
Make proper use of the new `git` package in dgeni-packages
2015-06-23 05:10:21 -07:00
Tsuyoshi Yoshizawa 0bb57d538f fix($location): allow navigating outside the original base URL
Previously, if you navigated outside of the current base URL angular
crashed with a `Cannot call method 'charAt' of undefined` error.

Closes #11302
Closes #4776
2015-06-19 18:41:47 +01:00
Peter Bacon Darwin 61a3fb676a fix($browser): prevent infinite digest if changing hash when there is no hashPrefix
The `window.location.hash' setter will strip of a single leading hash character
if it exists from the fragment  before joining the fragment value to the href
with a new hash character.

This meant that if we want the fragment to lead with a hash character, we
must do `window.location.hash = '##test'` to ensure that the first hash
character in the fragment is not lost.

The `$location.hash` setter works differently and assumes that the value
passed is the the full fragment, i.e. it does not attempt to strip off a
single leading hash character.

Previously, if you called, `$location.hash('#test')`, the leading hash was
being stripped and the resulting url fragment did not contain this hash:
`$location.hash()`, then became 'test' rather than `#test`, which led to
an infinite digest.

Closes #10423
Closes #12145
2015-06-17 14:02:31 +01:00
Peter Bacon Darwin f486ebe80b fix($location): do not get caught in infinite digest in IE9
Thanks to @hamfastgamgee for getting this fix in place.

Closes #11439
Closes #11675
Closes #11935
Closes #12083
2015-06-12 14:42:40 +01:00
Peter Bacon Darwin 03190fd896 chore(ngMock): check that ngMock.$browser.pollFns exists before emptying 2015-06-12 14:42:30 +01:00
Caitlin Potter 340e4da2eb test($location): ensure mock window can be wrapped by jqLite
Fixin da build

Closes #12086
2015-06-12 14:37:54 +01:00
Peter Bacon Darwin 46e4fa87fb test($locationSpec): refactor and clean up tests 2015-06-12 14:37:33 +01:00
Peter Bacon Darwin 45d43b9234 test($logSpec): don't pollute the global namespace with helpers 2015-06-11 14:32:35 +01:00
Conny Sjöblom 6b28aef1c5 fix(linky): allow case insensitive scheme detection
Closes #12073
Closes #12074
2015-06-11 12:16:07 +01:00
17 changed files with 2927 additions and 2575 deletions
+2 -3
View File
@@ -10,14 +10,14 @@ var Package = require('dgeni').Package;
module.exports = new Package('angularjs', [
require('dgeni-packages/ngdoc'),
require('dgeni-packages/nunjucks'),
require('dgeni-packages/examples')
require('dgeni-packages/examples'),
require('dgeni-packages/git')
])
.factory(require('./services/errorNamespaceMap'))
.factory(require('./services/getMinerrInfo'))
.factory(require('./services/getVersion'))
.factory(require('./services/gitData'))
.factory(require('./services/deployments/debug'))
.factory(require('./services/deployments/default'))
@@ -26,7 +26,6 @@ module.exports = new Package('angularjs', [
.factory(require('./inline-tag-defs/type'))
.processor(require('./processors/error-docs'))
.processor(require('./processors/index-page'))
.processor(require('./processors/keywords'))
-16
View File
@@ -1,16 +0,0 @@
"use strict";
var versionInfo = require('../../../lib/versions/version-info');
/**
* @dgService gitData
* @description
* Information from the local git repository
*/
module.exports = function gitData() {
return {
version: versionInfo.currentVersion,
versions: versionInfo.previousVersions,
info: versionInfo.gitRepoInfo
};
};
+22 -16
View File
@@ -2385,10 +2385,10 @@
}
},
"dgeni-packages": {
"version": "0.10.13",
"version": "0.10.17",
"dependencies": {
"catharsis": {
"version": "0.8.6",
"version": "0.8.7",
"dependencies": {
"underscore-contrib": {
"version": "0.3.0",
@@ -2404,10 +2404,10 @@
"version": "2.3.0",
"dependencies": {
"camel-case": {
"version": "1.1.1"
"version": "1.1.2"
},
"constant-case": {
"version": "1.1.0"
"version": "1.1.1"
},
"dot-case": {
"version": "1.1.1"
@@ -2428,7 +2428,7 @@
"version": "1.1.1"
},
"pascal-case": {
"version": "1.1.0"
"version": "1.1.1"
},
"path-case": {
"version": "1.1.1"
@@ -2440,10 +2440,10 @@
"version": "1.1.1"
},
"swap-case": {
"version": "1.1.0"
"version": "1.1.1"
},
"title-case": {
"version": "1.1.0"
"version": "1.1.1"
},
"upper-case": {
"version": "1.1.2"
@@ -2468,7 +2468,7 @@
}
},
"htmlparser2": {
"version": "3.8.2",
"version": "3.8.3",
"dependencies": {
"domhandler": {
"version": "2.3.0"
@@ -2518,21 +2518,21 @@
"version": "0.3.0",
"dependencies": {
"lru-cache": {
"version": "2.5.0"
"version": "2.6.4"
},
"sigmund": {
"version": "1.0.0"
"version": "1.0.1"
}
}
},
"nunjucks": {
"version": "1.2.0",
"version": "1.3.4",
"dependencies": {
"optimist": {
"version": "0.6.1",
"dependencies": {
"wordwrap": {
"version": "0.0.2"
"version": "0.0.3"
},
"minimist": {
"version": "0.0.10"
@@ -2552,10 +2552,10 @@
"version": "0.2.14",
"dependencies": {
"lru-cache": {
"version": "2.5.0"
"version": "2.6.4"
},
"sigmund": {
"version": "1.0.0"
"version": "1.0.1"
}
}
},
@@ -2582,10 +2582,10 @@
"version": "0.1.6"
},
"fsevents": {
"version": "0.3.5",
"version": "0.3.6",
"dependencies": {
"nan": {
"version": "1.5.3"
"version": "1.8.4"
}
}
}
@@ -2621,6 +2621,12 @@
}
}
},
"semver": {
"version": "4.3.6"
},
"shelljs": {
"version": "0.5.1"
},
"winston": {
"version": "0.7.3",
"dependencies": {
+1786 -1776
View File
File diff suppressed because it is too large Load Diff
+2 -2
View File
@@ -63,7 +63,7 @@ function Browser(window, document, $log, $sniffer) {
function getHash(url) {
var index = url.indexOf('#');
return index === -1 ? '' : url.substr(index + 1);
return index === -1 ? '' : url.substr(index);
}
/**
@@ -190,7 +190,7 @@ function Browser(window, document, $log, $sniffer) {
// Do the assignment again so that those two variables are referentially identical.
lastHistoryState = cachedState;
} else {
if (!sameBase) {
if (!sameBase || reloadLocation) {
reloadLocation = url;
}
if (replace) {
+1 -1
View File
@@ -2193,7 +2193,7 @@ function $CompileProvider($provide, $$sanitizeUriProvider) {
$compileNode.empty();
$templateRequest($sce.getTrustedResourceUrl(templateUrl))
$templateRequest(templateUrl)
.then(function(content) {
var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
+3 -3
View File
@@ -178,8 +178,8 @@
* @param {Object} angularEvent Synthetic event object.
* @param {String} src URL of content to load.
*/
var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce',
function($templateRequest, $anchorScroll, $animate, $sce) {
var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate',
function($templateRequest, $anchorScroll, $animate) {
return {
restrict: 'ECA',
priority: 400,
@@ -215,7 +215,7 @@ var ngIncludeDirective = ['$templateRequest', '$anchorScroll', '$animate', '$sce
}
};
scope.$watch($sce.parseAsResourceUrl(srcExp), function ngIncludeWatchAction(src) {
scope.$watch(srcExp, function ngIncludeWatchAction(src) {
var afterAnimation = function() {
if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) {
$anchorScroll();
+10 -2
View File
@@ -185,7 +185,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
var withoutBaseUrl = beginsWith(appBase, url) || beginsWith(appBaseNoFile, url);
var withoutHashUrl;
if (withoutBaseUrl.charAt(0) === '#') {
if (!isUndefined(withoutBaseUrl) && withoutBaseUrl.charAt(0) === '#') {
// The rest of the url starts with a hash so we have
// got either a hashbang path or a plain hash fragment
@@ -199,7 +199,15 @@ function LocationHashbangUrl(appBase, hashPrefix) {
// There was no hashbang path nor hash fragment:
// If we are in HTML5 mode we use what is left as the path;
// Otherwise we ignore what is left
withoutHashUrl = this.$$html5 ? withoutBaseUrl : '';
if (this.$$html5) {
withoutHashUrl = withoutBaseUrl;
} else {
withoutHashUrl = '';
if (isUndefined(withoutBaseUrl)) {
appBase = url;
this.replace();
}
}
}
parseAppUrl(withoutHashUrl, this);
+17 -6
View File
@@ -7,12 +7,14 @@ var $compileMinErr = minErr('$compile');
* @name $templateRequest
*
* @description
* The `$templateRequest` service downloads the provided template using `$http` and, upon success,
* stores the contents inside of `$templateCache`. If the HTTP request fails or the response data
* of the HTTP request is empty, a `$compile` error will be thrown (the exception can be thwarted
* by setting the 2nd parameter of the function to true).
* The `$templateRequest` service runs security checks then downloads the provided template using
* `$http` and, upon success, stores the contents inside of `$templateCache`. If the HTTP request
* fails or the response data of the HTTP request is empty, a `$compile` error will be thrown (the
* exception can be thwarted by setting the 2nd parameter of the function to true). Note that the
* contents of `$templateCache` are trusted, so the call to `$sce.getTrustedUrl(tpl)` is omitted
* when `tpl` is of type string and `$templateCache` has the matching entry.
*
* @param {string} tpl The HTTP request template URL
* @param {string|TrustedResourceUrl} tpl The HTTP request template URL
* @param {boolean=} ignoreRequestError Whether or not to ignore the exception when the request fails or the template is empty
*
* @return {Promise} the HTTP Promise for the given.
@@ -20,10 +22,19 @@ var $compileMinErr = minErr('$compile');
* @property {number} totalPendingRequests total amount of pending template requests being downloaded.
*/
function $TemplateRequestProvider() {
this.$get = ['$templateCache', '$http', '$q', function($templateCache, $http, $q) {
this.$get = ['$templateCache', '$http', '$q', '$sce', function($templateCache, $http, $q, $sce) {
function handleRequestFn(tpl, ignoreRequestError) {
handleRequestFn.totalPendingRequests++;
// We consider the template cache holds only trusted templates, so
// there's no need to go through whitelisting again for keys that already
// are included in there. This also makes Angular accept any script
// directive, no matter its name. However, we still need to unwrap trusted
// types.
if (!isString(tpl) || !$templateCache.get(tpl)) {
tpl = $sce.getTrustedResourceUrl(tpl);
}
var transformResponse = $http.defaults && $http.defaults.transformResponse;
if (isArray(transformResponse)) {
+2 -1
View File
@@ -2237,7 +2237,8 @@ if (window.jasmine || window.mocha) {
if (injector) {
injector.get('$rootElement').off();
injector.get('$browser').pollFns.length = 0;
var $browser = injector.get('$browser');
if ($browser.pollFns) $browser.pollFns.length = 0;
}
// clean up jquery's fragment cache
+1 -2
View File
@@ -591,9 +591,8 @@ function $RouteProvider() {
if (angular.isFunction(templateUrl)) {
templateUrl = templateUrl(nextRoute.params);
}
templateUrl = $sce.getTrustedResourceUrl(templateUrl);
if (angular.isDefined(templateUrl)) {
nextRoute.loadedTemplateUrl = templateUrl;
nextRoute.loadedTemplateUrl = $sce.valueOf(templateUrl);
template = $templateRequest(templateUrl);
}
}
+2 -2
View File
@@ -104,8 +104,8 @@
*/
angular.module('ngSanitize').filter('linky', ['$sanitize', function($sanitize) {
var LINKY_URL_REGEXP =
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/,
MAILTO_REGEXP = /^mailto:/;
/((ftp|https?):\/\/|(www\.)|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>"”’]/i,
MAILTO_REGEXP = /^mailto:/i;
return function(text, target) {
if (!text) return text;
+3 -1
View File
@@ -57,7 +57,9 @@ function MockWindow(options) {
return getHash(locationHref);
},
set hash(value) {
locationHref = stripHash(locationHref) + '#' + value;
// replace the hash with the new one (stripping off a leading hash if there is one)
// See hash setter spec: https://url.spec.whatwg.org/#urlutils-and-urlutilsreadonly-members
locationHref = stripHash(locationHref) + '#' + value.replace(/^#/,'');
},
replace: function(url) {
locationHref = url;
+12 -2
View File
@@ -1281,14 +1281,24 @@ describe('$compile', function() {
));
it('should not load cross domain templates by default', inject(
function($compile, $rootScope, $templateCache, $sce) {
function($compile, $rootScope) {
expect(function() {
$templateCache.put('http://example.com/should-not-load.html', 'Should not load even if in cache.');
$compile('<div class="crossDomainTemplate"></div>')($rootScope);
}).toThrowMinErr('$sce', 'insecurl', 'Blocked loading resource from url not allowed by $sceDelegate policy. URL: http://example.com/should-not-load.html');
}
));
it('should trust what is already in the template cache', inject(
function($compile, $httpBackend, $rootScope, $templateCache) {
$httpBackend.expect('GET', 'http://example.com/should-not-load.html').respond('<span>example.com/remote-version</span>');
$templateCache.put('http://example.com/should-not-load.html', '<span>example.com/cached-version</span>');
element = $compile('<div class="crossDomainTemplate"></div>')($rootScope);
expect(sortedHtml(element)).toEqual('<div class="crossDomainTemplate"></div>');
$rootScope.$digest();
expect(sortedHtml(element)).toEqual('<div class="crossDomainTemplate"><span>example.com/cached-version</span></div>');
}
));
it('should load cross domain templates when trusted', inject(
function($compile, $httpBackend, $rootScope, $sce) {
$httpBackend.expect('GET', 'http://example.com/trusted-template.html').respond('<span>example.com/trusted_template_contents</span>');
+1048 -736
View File
File diff suppressed because it is too large Load Diff
+7 -6
View File
@@ -1,12 +1,6 @@
/* global $LogProvider: false */
'use strict';
function initService(debugEnabled) {
return module(function($logProvider) {
$logProvider.debugEnabled(debugEnabled);
});
}
describe('$log', function() {
var $window, logger, log, warn, info, error, debug;
@@ -178,4 +172,11 @@ describe('$log', function() {
expect(errorArgs).toEqual(['abc', 'message\nsourceURL:123']);
});
});
function initService(debugEnabled) {
return module(function($logProvider) {
$logProvider.debugEnabled(debugEnabled);
});
}
});
+9
View File
@@ -20,6 +20,15 @@ describe('linky', function() {
expect(linky(undefined)).not.toBeDefined();
});
it('should be case-insensitive', function() {
expect(linky('WWW.example.com')).toEqual('<a href="http://WWW.example.com">WWW.example.com</a>');
expect(linky('WWW.EXAMPLE.COM')).toEqual('<a href="http://WWW.EXAMPLE.COM">WWW.EXAMPLE.COM</a>');
expect(linky('HTTP://www.example.com')).toEqual('<a href="HTTP://www.example.com">HTTP://www.example.com</a>');
expect(linky('HTTP://example.com')).toEqual('<a href="HTTP://example.com">HTTP://example.com</a>');
expect(linky('HTTPS://www.example.com')).toEqual('<a href="HTTPS://www.example.com">HTTPS://www.example.com</a>');
expect(linky('HTTPS://example.com')).toEqual('<a href="HTTPS://example.com">HTTPS://example.com</a>');
});
it('should handle www.', function() {
expect(linky('www.example.com')).toEqual('<a href="http://www.example.com">www.example.com</a>');
});