diff --git a/src/ng/sce.js b/src/ng/sce.js index 60356097c9c0..988d45bfd9f8 100644 --- a/src/ng/sce.js +++ b/src/ng/sce.js @@ -131,12 +131,6 @@ function $SceDelegateProvider() { return resourceUrlBlacklist; }; - // Helper functions for matching resource urls by policy. - function isCompatibleProtocol(documentProtocol, resourceProtocol) { - return ((documentProtocol === resourceProtocol) || - (documentProtocol === "http:" && resourceProtocol === "https:")); - } - this.$get = ['$log', '$document', '$injector', '$$urlUtils', function( $log, $document, $injector, $$urlUtils) { @@ -179,32 +173,38 @@ function $SceDelegateProvider() { return allowed; } - function generateHolderType(base) { + function generateHolderType(base, useCache) { + var cacheInstances = {}; var holderType = function TrustedValueHolderType(trustedValue) { + if (cacheInstances[trustedValue] && useCache) { + return cacheInstances[trustedValue]; + } + + cacheInstances[trustedValue] = this; this.$$unwrapTrustedValue = function() { return trustedValue; }; }; if (base) { - holderType.prototype = new base(); + holderType.prototype = new base(''); } holderType.prototype.valueOf = function sceValueOf() { return this.$$unwrapTrustedValue(); - } + }; holderType.prototype.toString = function sceToString() { return this.$$unwrapTrustedValue().toString(); - } + }; return holderType; } var trustedValueHolderBase = generateHolderType(), byType = {}; - byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase); - byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL]); + byType[SCE_CONTEXTS.HTML] = generateHolderType(trustedValueHolderBase, true); + byType[SCE_CONTEXTS.CSS] = generateHolderType(trustedValueHolderBase, true); + byType[SCE_CONTEXTS.URL] = generateHolderType(trustedValueHolderBase, true); + byType[SCE_CONTEXTS.JS] = generateHolderType(trustedValueHolderBase, true); + byType[SCE_CONTEXTS.RESOURCE_URL] = generateHolderType(byType[SCE_CONTEXTS.URL], true); /** * @ngdoc method @@ -341,7 +341,7 @@ function $SceDelegateProvider() { * # Strict Contextual Escaping * * Strict Contextual Escaping (SCE) is a mode in which AngularJS requires bindings in certain - * contexts to result in a value that is marked as safe to use for that context One example of such + * contexts to result in a value that is marked as safe to use for that context. One example of such * a context is binding arbitrary html controlled by the user via `ng-bind-html`. We refer to these * contexts as privileged or SCE contexts. * @@ -419,7 +419,7 @@ function $SceDelegateProvider() { * By default, Angular only loads templates from the same domain and protocol as the application * document. This is done by calling {@link ng.$sce#getTrustedResourceUrl * $sce.getTrustedResourceUrl} on the template URL. To load templates from other domains and/or - * protocols, you may either either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist + * protocols, you may either {@link ng.$sceDelegateProvider#resourceUrlWhitelist whitelist * them} or {@link ng.$sce#trustAsResourceUrl wrap it} into a trusted value. * * *Please note*: @@ -935,13 +935,13 @@ function $SceProvider() { var lName = lowercase(name); sce[camelCase("parse_as_" + lName)] = function (expr) { return parse(enumValue, expr); - } + }; sce[camelCase("get_trusted_" + lName)] = function (value) { return getTrusted(enumValue, value); - } + }; sce[camelCase("trust_as_" + lName)] = function (value) { return trustAs(enumValue, value); - } + }; }); return sce; diff --git a/test/ng/sceSpecs.js b/test/ng/sceSpecs.js index 1eb382f6a887..e2e44b7c1c06 100644 --- a/test/ng/sceSpecs.js +++ b/test/ng/sceSpecs.js @@ -173,6 +173,14 @@ describe('SCE', function() { expect($sce.getTrustedHtml(wrappedValue)).toBe(originalValue); expect(wrappedValue.toString()).toBe(originalValue.toString()); })); + + it('should be watchable', inject(function ($rootScope, $sce) { + $rootScope.$watch(function() { return $sce.trustAsHtml(''); }, function(value) { + expect($sce.getTrustedHtml(value)).toBe(''); + }); + $rootScope.$apply(); + })); + });