From e8d7496b62f0b42843aeb9a6f86b6c004d9b56d2 Mon Sep 17 00:00:00 2001 From: Georgios Kalpakas Date: Wed, 27 Jul 2016 19:35:48 +0300 Subject: [PATCH] perf($parse): improve performance of assignment expressions There was a ~5% improvement in the added `parsed-expressions-bp/assignment` benchmark (which only contains assignment expressions). In real-world applications, the time spent in assignment expressions will be a tiny fragment of the overall processing time, though. Closes #14957 --- benchmarks/parsed-expressions-bp/app.js | 19 ++++---- benchmarks/parsed-expressions-bp/main.html | 17 +++++++ src/ng/parse.js | 56 ++++++++++++---------- 3 files changed, 57 insertions(+), 35 deletions(-) diff --git a/benchmarks/parsed-expressions-bp/app.js b/benchmarks/parsed-expressions-bp/app.js index 1323705b6..4b93c9770 100755 --- a/benchmarks/parsed-expressions-bp/app.js +++ b/benchmarks/parsed-expressions-bp/app.js @@ -23,7 +23,6 @@ app.directive('bmPeWatch', function() { return function($scope, $element, $attrs) { $scope.$watch($attrs.bmPeWatch, function(val) { $element.text(val); - }); }; } @@ -55,19 +54,19 @@ app.controller('DataController', function($scope, $rootScope) { var star = '*'; - $scope.func = function() { return star;}; + $scope.func = function() { return star; }; for (var i = 0; i < totalRows; i++) { data.push({ index: i, - odd: i % 2 === 0, - even: i % 2 === 1, - str0: "foo-" + Math.random() * Date.now(), - str1: "bar-" + Math.random() * Date.now(), - str2: "baz-" + Math.random() * Date.now(), - num0: Math.random() * Date.now(), - num1: Math.random() * Date.now(), - num2: Math.random() * Date.now(), + odd: i % 2 === 0, + even: i % 2 === 1, + str0: 'foo-' + Math.random() * Date.now(), + str1: 'bar-' + Math.random() * Date.now(), + str2: 'baz-' + Math.random() * Date.now(), + num0: Math.random() * Date.now(), + num1: Math.random() * Date.now(), + num2: Math.random() * Date.now(), date0: new Date(Math.random() * Date.now()), date1: new Date(Math.random() * Date.now()), date2: new Date(Math.random() * Date.now()), diff --git a/benchmarks/parsed-expressions-bp/main.html b/benchmarks/parsed-expressions-bp/main.html index 7358b9db1..8b71317bf 100755 --- a/benchmarks/parsed-expressions-bp/main.html +++ b/benchmarks/parsed-expressions-bp/main.html @@ -52,6 +52,11 @@ +
  • + + +
  • +
  • @@ -197,6 +202,18 @@
  • +
  • + + + + + + + + + +
  • +
  • diff --git a/src/ng/parse.js b/src/ng/parse.js index 8c19d9e0d..3a81c1e99 100644 --- a/src/ng/parse.js +++ b/src/ng/parse.js @@ -13,6 +13,25 @@ var $parseMinErr = minErr('$parse'); +var ARRAY_CTOR = [].constructor; +var BOOLEAN_CTOR = (false).constructor; +var FUNCTION_CTOR = Function.constructor; +var NUMBER_CTOR = (0).constructor; +var OBJECT_CTOR = {}.constructor; +var STRING_CTOR = ''.constructor; +var ARRAY_CTOR_PROTO = ARRAY_CTOR.prototype; +var BOOLEAN_CTOR_PROTO = BOOLEAN_CTOR.prototype; +var FUNCTION_CTOR_PROTO = FUNCTION_CTOR.prototype; +var NUMBER_CTOR_PROTO = NUMBER_CTOR.prototype; +var OBJECT_CTOR_PROTO = OBJECT_CTOR.prototype; +var STRING_CTOR_PROTO = STRING_CTOR.prototype; + +var CALL = FUNCTION_CTOR_PROTO.call; +var APPLY = FUNCTION_CTOR_PROTO.apply; +var BIND = FUNCTION_CTOR_PROTO.bind; + +var objectValueOf = OBJECT_CTOR_PROTO.valueOf; + // Sandboxing Angular Expressions // ------------------------------ // Angular expressions are generally considered safe because these expressions only have direct @@ -93,10 +112,6 @@ function ensureSafeObject(obj, fullExpression) { return obj; } -var CALL = Function.prototype.call; -var APPLY = Function.prototype.apply; -var BIND = Function.prototype.bind; - function ensureSafeFunction(obj, fullExpression) { if (obj) { if (obj.constructor === obj) { @@ -113,25 +128,18 @@ function ensureSafeFunction(obj, fullExpression) { function ensureSafeAssignContext(obj, fullExpression) { if (obj) { - var booleanConstructor = (false).constructor; - var numberConstructor = (0).constructor; - var stringConstructor = ''.constructor; - var objectConstructor = {}.constructor; - var arrayConstructor = [].constructor; - var functionConstructor = Function.constructor; - - if (obj === booleanConstructor || - obj === numberConstructor || - obj === stringConstructor || - obj === objectConstructor || - obj === arrayConstructor || - obj === functionConstructor || - obj === booleanConstructor.prototype || - obj === numberConstructor.prototype || - obj === stringConstructor.prototype || - obj === objectConstructor.prototype || - obj === arrayConstructor.prototype || - obj === functionConstructor.prototype) { + if (obj === ARRAY_CTOR || + obj === BOOLEAN_CTOR || + obj === FUNCTION_CTOR || + obj === NUMBER_CTOR || + obj === OBJECT_CTOR || + obj === STRING_CTOR || + obj === ARRAY_CTOR_PROTO || + obj === BOOLEAN_CTOR_PROTO || + obj === FUNCTION_CTOR_PROTO || + obj === NUMBER_CTOR_PROTO || + obj === OBJECT_CTOR_PROTO || + obj === STRING_CTOR_PROTO) { throw $parseMinErr('isecaf', 'Assigning to a constructor or its prototype is disallowed! Expression: {0}', fullExpression); @@ -1794,8 +1802,6 @@ function isPossiblyDangerousMemberName(name) { return name === 'constructor'; } -var objectValueOf = Object.prototype.valueOf; - function getValueOf(value) { return isFunction(value.valueOf) ? value.valueOf() : objectValueOf.call(value); }