11/**
2- * @license AngularJS v1.0.0rc6
2+ * @license AngularJS v1.0.0rc7
33 * (c) 2010-2012 Google, Inc. http://angularjs.org
44 * License: MIT
55 */
@@ -1243,11 +1243,11 @@ function setupModuleLoader(window) {
12431243 * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
12441244 */
12451245var version = {
1246- full : '1.0.0rc6 ' , // all of these placeholder strings will be replaced by rake's
1246+ full : '1.0.0rc7 ' , // all of these placeholder strings will be replaced by rake's
12471247 major : 1 , // compile task
12481248 minor : 0 ,
12491249 dot : 0 ,
1250- codeName : 'runny-nose '
1250+ codeName : 'rc-generation '
12511251} ;
12521252
12531253
@@ -1305,6 +1305,7 @@ function publishExternalAPI(angular){
13051305 ngClass : ngClassDirective ,
13061306 ngClassEven : ngClassEvenDirective ,
13071307 ngClassOdd : ngClassOddDirective ,
1308+ ngCsp : ngCspDirective ,
13081309 ngCloak : ngCloakDirective ,
13091310 ngController : ngControllerDirective ,
13101311 ngForm : ngFormDirective ,
@@ -1873,8 +1874,8 @@ function createEventHandler(element) {
18731874
18741875 // Remove monkey-patched methods (IE),
18751876 // as they would cause memory leaks in IE8.
1876- if ( msie < 8 ) {
1877- // IE7 does not allow to delete property on native object
1877+ if ( msie <= 8 ) {
1878+ // IE7/8 does not allow to delete property on native object
18781879 event . preventDefault = null ;
18791880 event . stopPropagation = null ;
18801881 event . isDefaultPrevented = null ;
@@ -1918,14 +1919,12 @@ forEach({
19181919 bindFn ( element , 'mouseover' , function ( event ) {
19191920 counter ++ ;
19201921 if ( counter == 1 ) {
1921- event . type = 'mouseenter' ;
19221922 mouseenter ( event ) ;
19231923 }
19241924 } ) ;
19251925 bindFn ( element , 'mouseout' , function ( event ) {
19261926 counter -- ;
19271927 if ( counter == 0 ) {
1928- event . type = 'mouseleave' ;
19291928 mouseleave ( event ) ;
19301929 }
19311930 } ) ;
@@ -5277,7 +5276,7 @@ var OPERATORS = {
52775276} ;
52785277var ESCAPE = { "n" :"\n" , "f" :"\f" , "r" :"\r" , "t" :"\t" , "v" :"\v" , "'" :"'" , '"' :'"' } ;
52795278
5280- function lex ( text ) {
5279+ function lex ( text , csp ) {
52815280 var tokens = [ ] ,
52825281 token ,
52835282 index = 0 ,
@@ -5437,7 +5436,7 @@ function lex(text){
54375436 if ( OPERATORS . hasOwnProperty ( ident ) ) {
54385437 token . fn = token . json = OPERATORS [ ident ] ;
54395438 } else {
5440- var getter = getterFn ( ident ) ;
5439+ var getter = getterFn ( ident , csp ) ;
54415440 token . fn = extend ( function ( self , locals ) {
54425441 return ( getter ( self , locals ) ) ;
54435442 } , {
@@ -5511,10 +5510,10 @@ function lex(text){
55115510
55125511/////////////////////////////////////////
55135512
5514- function parser ( text , json , $filter ) {
5513+ function parser ( text , json , $filter , csp ) {
55155514 var ZERO = valueFn ( 0 ) ,
55165515 value ,
5517- tokens = lex ( text ) ,
5516+ tokens = lex ( text , csp ) ,
55185517 assignment = _assignment ,
55195518 functionCall = _functionCall ,
55205519 fieldAccess = _fieldAccess ,
@@ -5782,7 +5781,7 @@ function parser(text, json, $filter){
57825781
57835782 function _fieldAccess ( object ) {
57845783 var field = expect ( ) . text ;
5785- var getter = getterFn ( field ) ;
5784+ var getter = getterFn ( field , csp ) ;
57865785 return extend (
57875786 function ( self , locals ) {
57885787 return getter ( object ( self , locals ) , locals ) ;
@@ -5935,32 +5934,119 @@ function getter(obj, path, bindFnToScope) {
59355934
59365935var getterFnCache = { } ;
59375936
5938- function getterFn ( path ) {
5937+ /**
5938+ * Implementation of the "Black Hole" variant from:
5939+ * - http://jsperf.com/angularjs-parse-getter/4
5940+ * - http://jsperf.com/path-evaluation-simplified/7
5941+ */
5942+ function cspSafeGetterFn ( key0 , key1 , key2 , key3 , key4 ) {
5943+ return function ( scope , locals ) {
5944+ var pathVal = ( locals && locals . hasOwnProperty ( key0 ) ) ? locals : scope ,
5945+ promise ;
5946+
5947+ if ( ! pathVal ) return pathVal ;
5948+
5949+ pathVal = pathVal [ key0 ] ;
5950+ if ( pathVal && pathVal . then ) {
5951+ if ( ! ( "$$v" in pathVal ) ) {
5952+ promise = pathVal ;
5953+ promise . $$v = undefined ;
5954+ promise . then ( function ( val ) { promise . $$v = val ; } ) ;
5955+ }
5956+ pathVal = pathVal . $$v ;
5957+ }
5958+ if ( ! key1 || ! pathVal ) return pathVal ;
5959+
5960+ pathVal = pathVal [ key1 ] ;
5961+ if ( pathVal && pathVal . then ) {
5962+ if ( ! ( "$$v" in pathVal ) ) {
5963+ promise = pathVal ;
5964+ promise . $$v = undefined ;
5965+ promise . then ( function ( val ) { promise . $$v = val ; } ) ;
5966+ }
5967+ pathVal = pathVal . $$v ;
5968+ }
5969+ if ( ! key2 || ! pathVal ) return pathVal ;
5970+
5971+ pathVal = pathVal [ key2 ] ;
5972+ if ( pathVal && pathVal . then ) {
5973+ if ( ! ( "$$v" in pathVal ) ) {
5974+ promise = pathVal ;
5975+ promise . $$v = undefined ;
5976+ promise . then ( function ( val ) { promise . $$v = val ; } ) ;
5977+ }
5978+ pathVal = pathVal . $$v ;
5979+ }
5980+ if ( ! key3 || ! pathVal ) return pathVal ;
5981+
5982+ pathVal = pathVal [ key3 ] ;
5983+ if ( pathVal && pathVal . then ) {
5984+ if ( ! ( "$$v" in pathVal ) ) {
5985+ promise = pathVal ;
5986+ promise . $$v = undefined ;
5987+ promise . then ( function ( val ) { promise . $$v = val ; } ) ;
5988+ }
5989+ pathVal = pathVal . $$v ;
5990+ }
5991+ if ( ! key4 || ! pathVal ) return pathVal ;
5992+
5993+ pathVal = pathVal [ key4 ] ;
5994+ if ( pathVal && pathVal . then ) {
5995+ if ( ! ( "$$v" in pathVal ) ) {
5996+ promise = pathVal ;
5997+ promise . $$v = undefined ;
5998+ promise . then ( function ( val ) { promise . $$v = val ; } ) ;
5999+ }
6000+ pathVal = pathVal . $$v ;
6001+ }
6002+ return pathVal ;
6003+ } ;
6004+ } ;
6005+
6006+ function getterFn ( path , csp ) {
59396007 if ( getterFnCache . hasOwnProperty ( path ) ) {
59406008 return getterFnCache [ path ] ;
59416009 }
59426010
5943- var fn , code = 'var l, fn, p;\n' ;
5944- forEach ( path . split ( '.' ) , function ( key , index ) {
5945- code += 'if(!s) return s;\n' +
5946- 'l=s;\n' +
5947- 's=' + ( index
5948- // we simply direference 's' on any .dot notation
5949- ? 's'
5950- // but if we are first then we check locals firs, and if so read it first
5951- : '((k&&k.hasOwnProperty("' + key + '"))?k:s)' ) + '["' + key + '"]' + ';\n' +
5952- 'if (s && s.then) {\n' +
5953- ' if (!("$$v" in s)) {\n' +
5954- ' p=s;\n' +
5955- ' p.$$v = undefined;\n' +
5956- ' p.then(function(v) {p.$$v=v;});\n' +
5957- '}\n' +
5958- ' s=s.$$v\n' +
5959- '}\n' ;
5960- } ) ;
5961- code += 'return s;' ;
5962- fn = Function ( 's' , 'k' , code ) ;
5963- fn . toString = function ( ) { return code ; } ;
6011+ var pathKeys = path . split ( '.' ) ,
6012+ pathKeysLength = pathKeys . length ,
6013+ fn ;
6014+
6015+ if ( csp ) {
6016+ fn = ( pathKeysLength < 6 )
6017+ ? cspSafeGetterFn ( pathKeys [ 0 ] , pathKeys [ 1 ] , pathKeys [ 2 ] , pathKeys [ 3 ] , pathKeys [ 4 ] )
6018+ : function ( scope , locals ) {
6019+ var i = 0 , val ;
6020+ do {
6021+ val = cspSafeGetterFn (
6022+ pathKeys [ i ++ ] , pathKeys [ i ++ ] , pathKeys [ i ++ ] , pathKeys [ i ++ ] , pathKeys [ i ++ ]
6023+ ) ( scope , locals ) ;
6024+ locals = undefined ; // clear after first iteration
6025+ } while ( i < pathKeysLength ) ;
6026+ } ;
6027+ } else {
6028+ var code = 'var l, fn, p;\n' ;
6029+ forEach ( pathKeys , function ( key , index ) {
6030+ code += 'if(!s) return s;\n' +
6031+ 'l=s;\n' +
6032+ 's=' + ( index
6033+ // we simply dereference 's' on any .dot notation
6034+ ? 's'
6035+ // but if we are first then we check locals first, and if so read it first
6036+ : '((k&&k.hasOwnProperty("' + key + '"))?k:s)' ) + '["' + key + '"]' + ';\n' +
6037+ 'if (s && s.then) {\n' +
6038+ ' if (!("$$v" in s)) {\n' +
6039+ ' p=s;\n' +
6040+ ' p.$$v = undefined;\n' +
6041+ ' p.then(function(v) {p.$$v=v;});\n' +
6042+ '}\n' +
6043+ ' s=s.$$v\n' +
6044+ '}\n' ;
6045+ } ) ;
6046+ code += 'return s;' ;
6047+ fn = Function ( 's' , 'k' , code ) ; // s=scope, k=locals
6048+ fn . toString = function ( ) { return code ; } ;
6049+ }
59646050
59656051 return getterFnCache [ path ] = fn ;
59666052}
@@ -5969,13 +6055,13 @@ function getterFn(path) {
59696055
59706056function $ParseProvider ( ) {
59716057 var cache = { } ;
5972- this . $get = [ '$filter' , function ( $filter ) {
6058+ this . $get = [ '$filter' , '$sniffer' , function ( $filter , $sniffer ) {
59736059 return function ( exp ) {
59746060 switch ( typeof exp ) {
59756061 case 'string' :
59766062 return cache . hasOwnProperty ( exp )
59776063 ? cache [ exp ]
5978- : cache [ exp ] = parser ( exp , false , $filter ) ;
6064+ : cache [ exp ] = parser ( exp , false , $filter , $sniffer . csp ) ;
59796065 case 'function' :
59806066 return exp ;
59816067 default :
@@ -7551,7 +7637,9 @@ function $SnifferProvider() {
75517637 }
75527638
75537639 return eventSupport [ event ] ;
7554- }
7640+ } ,
7641+ // TODO(i): currently there is no way to feature detect CSP without triggering alerts
7642+ csp : false
75557643 } ;
75567644 } ] ;
75577645}
@@ -11373,7 +11461,7 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
1137311461 * @description
1137411462 * Creates a binding that will innerHTML the result of evaluating the `expression` into the current
1137511463 * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if
11376- * {@link angular.module.ng.$compileProvider .directive.ngBindHtml ngBindHtml} directive is too
11464+ * {@link angular.module.ngSanitize .directive.ngBindHtml ngBindHtml} directive is too
1137711465 * restrictive and when you absolutely trust the source of the content you are binding to.
1137811466 *
1137911467 * See {@link angular.module.ngSanitize.$sanitize $sanitize} docs for examples.
@@ -11694,6 +11782,32 @@ var ngControllerDirective = [function() {
1169411782 } ;
1169511783} ] ;
1169611784
11785+ /**
11786+ * @ngdoc directive
11787+ * @name angular.module.ng.$compileProvider.directive.ngCsp
11788+ * @priority 1000
11789+ *
11790+ * @description
11791+ * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support.
11792+ * This directive should be used on the root element of the application (typically the `<html>`
11793+ * element or other element with the {@link angular.module.ng.$compileProvider.directive.ngApp ngApp}
11794+ * directive).
11795+ *
11796+ * If enabled the performance of template expression evaluator will suffer slightly, so don't enable
11797+ * this mode unless you need it.
11798+ *
11799+ * @element html
11800+ */
11801+
11802+ var ngCspDirective = [ '$sniffer' , function ( $sniffer ) {
11803+ return {
11804+ priority : 1000 ,
11805+ compile : function ( ) {
11806+ $sniffer . csp = true ;
11807+ }
11808+ } ;
11809+ } ] ;
11810+
1169711811/**
1169811812 * @ngdoc directive
1169911813 * @name angular.module.ng.$compileProvider.directive.ngClick
0 commit comments