From 891d1fb39e9ca1550ef5eec39eb8473197d19d92 Mon Sep 17 00:00:00 2001
From: Sean Lilley <lilleyse@gmail.com>
Date: Tue, 24 Jan 2017 12:29:46 -0500
Subject: [PATCH 1/7] Change typeof(variable) to typeof variable

---
 Source/Scene/Cesium3DTileStyle.js | 10 +++---
 Source/Scene/Expression.js        | 60 +++++++++++++++----------------
 2 files changed, 35 insertions(+), 35 deletions(-)

diff --git a/Source/Scene/Cesium3DTileStyle.js b/Source/Scene/Cesium3DTileStyle.js
index 2507b8b5582..fb081757c4e 100644
--- a/Source/Scene/Cesium3DTileStyle.js
+++ b/Source/Scene/Cesium3DTileStyle.js
@@ -109,7 +109,7 @@ define([
         var pointSizeExpression = defaultValue(styleJson.pointSize, DEFAULT_JSON_NUMBER_EXPRESSION);
 
         var color;
-        if (typeof(colorExpression) === 'string') {
+        if (typeof colorExpression === 'string') {
             color = new Expression(colorExpression);
         } else if (defined(colorExpression.conditions)) {
             color = new ConditionsExpression(colorExpression);
@@ -118,9 +118,9 @@ define([
         that._color = color;
 
         var show;
-        if (typeof(showExpression) === 'boolean') {
+        if (typeof showExpression === 'boolean') {
             show = new Expression(String(showExpression));
-        } else if (typeof(showExpression) === 'string') {
+        } else if (typeof showExpression === 'string') {
             show = new Expression(showExpression);
         } else if (defined(showExpression.conditions)) {
             show = new ConditionsExpression(showExpression);
@@ -129,9 +129,9 @@ define([
         that._show = show;
 
         var pointSize;
-        if (typeof(pointSizeExpression) === 'number') {
+        if (typeof pointSizeExpression === 'number') {
             pointSize = new Expression(String(pointSizeExpression));
-        } else if (typeof(pointSizeExpression) === 'string') {
+        } else if (typeof pointSizeExpression === 'string') {
             pointSize = new Expression(pointSizeExpression);
         } else if (defined(pointSizeExpression.conditions)) {
             pointSize = new ConditionsExpression(pointSizeExpression);
diff --git a/Source/Scene/Expression.js b/Source/Scene/Expression.js
index 148a877c372..ab9c0dd22fc 100644
--- a/Source/Scene/Expression.js
+++ b/Source/Scene/Expression.js
@@ -148,7 +148,7 @@ define([
      */
     function Expression(expression) {
         //>>includeStart('debug', pragmas.debug);
-        if (typeof(expression) !== 'string') {
+        if (typeof expression !== 'string') {
             throw new DeveloperError('expression must be a string.');
         }
         //>>includeEnd('debug');
@@ -324,7 +324,7 @@ define([
     }
 
     function parseLiteral(ast) {
-        var type = typeof(ast.value);
+        var type = typeof ast.value;
         if (ast.value === null) {
             return new Node(ExpressionNodeType.LITERAL_NULL, null);
         } else if (type === 'boolean') {
@@ -777,7 +777,7 @@ define([
         var evaluate = unaryFunctions[call];
         return function(feature) {
             var left = this._left.evaluate(feature);
-            if (typeof(left) === 'number') {
+            if (typeof left === 'number') {
                 return evaluate(left);
             } else if (left instanceof Cartesian2) {
                 return Cartesian2.fromElements(evaluate(left.x), evaluate(left.y), ScratchStorage.getCartesian2());
@@ -874,7 +874,7 @@ define([
         var argsLength = args.length;
         for (var i = 0; i < argsLength; ++i) {
             var value = args[i].evaluate(frameState, feature);
-            if (typeof(value) === 'number') {
+            if (typeof value === 'number') {
                 components.push(value);
             } else if (value instanceof Cartesian2) {
                 components.push(value.x, value.y);
@@ -1013,7 +1013,7 @@ define([
     Node.prototype._evaluateNot = function(frameState, feature) {
         var left = this._left.evaluate(frameState, feature);
         //>>includeStart('debug', pragmas.debug);
-        if (typeof(left) !== 'boolean') {
+        if (typeof left !== 'boolean') {
             throw new DeveloperError('Operator "!" requires a boolean argument. Argument is ' + left + '.');
         }
         //>>includeEnd('debug');
@@ -1028,7 +1028,7 @@ define([
             return Cartesian3.negate(left, ScratchStorage.getCartesian3());
         } else if (left instanceof Cartesian4) {
             return Cartesian4.negate(left, ScratchStorage.getCartesian4());
-        } else if (typeof(left) === 'number') {
+        } else if (typeof left === 'number') {
             return -left;
         }
 
@@ -1042,7 +1042,7 @@ define([
         var left = this._left.evaluate(frameState, feature);
 
         //>>includeStart('debug', pragmas.debug);
-        if (!((left instanceof Cartesian2) || (left instanceof Cartesian3) || (left instanceof Cartesian4) || (typeof(left) === 'number'))) {
+        if (!((left instanceof Cartesian2) || (left instanceof Cartesian3) || (left instanceof Cartesian4) || (typeof left === 'number'))) {
             throw new DeveloperError('Operator "+" requires a vector or number argument. Argument is ' + left + '.');
         }
         //>>includeEnd('debug');
@@ -1055,7 +1055,7 @@ define([
         var right = this._right.evaluate(frameState, feature);
 
         //>>includeStart('debug', pragmas.debug);
-        if ((typeof(left) !== 'number') || (typeof(right) !== 'number')) {
+        if ((typeof left !== 'number') || (typeof right !== 'number')) {
             throw new DeveloperError('Operator "<" requires number arguments. Arguments are ' + left + ' and ' + right + '.');
         }
         //>>includeEnd('debug');
@@ -1068,7 +1068,7 @@ define([
         var right = this._right.evaluate(frameState, feature);
 
         //>>includeStart('debug', pragmas.debug);
-        if ((typeof(left) !== 'number') || (typeof(right) !== 'number')) {
+        if ((typeof left !== 'number') || (typeof right !== 'number')) {
             throw new DeveloperError('Operator "<=" requires number arguments. Arguments are ' + left + ' and ' + right + '.');
         }
         //>>includeEnd('debug');
@@ -1081,7 +1081,7 @@ define([
         var right = this._right.evaluate(frameState, feature);
 
         //>>includeStart('debug', pragmas.debug);
-        if ((typeof(left) !== 'number') || (typeof(right) !== 'number')) {
+        if ((typeof left !== 'number') || (typeof right !== 'number')) {
             throw new DeveloperError('Operator ">" requires number arguments. Arguments are ' + left + ' and ' + right + '.');
         }
         //>>includeEnd('debug');
@@ -1094,7 +1094,7 @@ define([
         var right = this._right.evaluate(frameState, feature);
 
         //>>includeStart('debug', pragmas.debug);
-        if ((typeof(left) !== 'number') || (typeof(right) !== 'number')) {
+        if ((typeof left !== 'number') || (typeof right !== 'number')) {
             throw new DeveloperError('Operator ">=" requires number arguments. Arguments are ' + left + ' and ' + right + '.');
         }
         //>>includeEnd('debug');
@@ -1105,7 +1105,7 @@ define([
     Node.prototype._evaluateOr = function(frameState, feature) {
         var left = this._left.evaluate(frameState, feature);
         //>>includeStart('debug', pragmas.debug);
-        if (typeof(left) !== 'boolean') {
+        if (typeof left !== 'boolean') {
             throw new DeveloperError('Operator "||" requires boolean arguments. First argument is ' + left + '.');
         }
         //>>includeEnd('debug');
@@ -1117,7 +1117,7 @@ define([
 
         var right = this._right.evaluate(frameState, feature);
         //>>includeStart('debug', pragmas.debug);
-        if (typeof(right) !== 'boolean') {
+        if (typeof right !== 'boolean') {
             throw new DeveloperError('Operator "||" requires boolean arguments. Second argument is ' + right + '.');
         }
         //>>includeEnd('debug');
@@ -1127,7 +1127,7 @@ define([
     Node.prototype._evaluateAnd = function(frameState, feature) {
         var left = this._left.evaluate(frameState, feature);
         //>>includeStart('debug', pragmas.debug);
-        if (typeof(left) !== 'boolean') {
+        if (typeof left !== 'boolean') {
             throw new DeveloperError('Operator "&&" requires boolean arguments. First argument is ' + left + '.');
         }
         //>>includeEnd('debug');
@@ -1139,7 +1139,7 @@ define([
 
         var right = this._right.evaluate(frameState, feature);
         //>>includeStart('debug', pragmas.debug);
-        if (typeof(right) !== 'boolean') {
+        if (typeof right !== 'boolean') {
             throw new DeveloperError('Operator "&&" requires boolean arguments. Second argument is ' + right + '.');
         }
         //>>includeEnd('debug');
@@ -1155,10 +1155,10 @@ define([
             return Cartesian3.add(left, right, ScratchStorage.getCartesian3());
         } else if ((right instanceof Cartesian4) && (left instanceof Cartesian4)) {
             return Cartesian4.add(left, right, ScratchStorage.getCartesian4());
-        } else if ((typeof(left) === 'string') || (typeof(right) === 'string')) {
+        } else if ((typeof left === 'string') || (typeof right === 'string')) {
             // If only one argument is a string the other argument calls its toString function.
             return left + right;
-        } else if ((typeof(left) === 'number') && (typeof(right) === 'number')) {
+        } else if ((typeof left === 'number') && (typeof right === 'number')) {
             return left + right;
         }
 
@@ -1178,7 +1178,7 @@ define([
             return Cartesian3.subtract(left, right, ScratchStorage.getCartesian3());
         } else if ((right instanceof Cartesian4) && (left instanceof Cartesian4)) {
             return Cartesian4.subtract(left, right, ScratchStorage.getCartesian4());
-        } else if ((typeof(left) === 'number') && (typeof(right) === 'number')) {
+        } else if ((typeof left === 'number') && (typeof right === 'number')) {
             return left - right;
         }
 
@@ -1194,23 +1194,23 @@ define([
         var right = this._right.evaluate(frameState, feature);
         if ((right instanceof Cartesian2) && (left instanceof Cartesian2)) {
             return Cartesian2.multiplyComponents(left, right, ScratchStorage.getCartesian2());
-        } else if ((right instanceof Cartesian2) && (typeof(left) === 'number')) {
+        } else if ((right instanceof Cartesian2) && (typeof left === 'number')) {
             return Cartesian2.multiplyByScalar(right, left, ScratchStorage.getCartesian2());
-        } else if ((left instanceof Cartesian2) && (typeof(right) === 'number')) {
+        } else if ((left instanceof Cartesian2) && (typeof right === 'number')) {
             return Cartesian2.multiplyByScalar(left, right, ScratchStorage.getCartesian2());
         } else if ((right instanceof Cartesian3) && (left instanceof Cartesian3)) {
             return Cartesian3.multiplyComponents(left, right, ScratchStorage.getCartesian3());
-        } else if ((right instanceof Cartesian3) && (typeof(left) === 'number')) {
+        } else if ((right instanceof Cartesian3) && (typeof left === 'number')) {
             return Cartesian3.multiplyByScalar(right, left, ScratchStorage.getCartesian3());
-        } else if ((left instanceof Cartesian3) && (typeof(right) === 'number')) {
+        } else if ((left instanceof Cartesian3) && (typeof right === 'number')) {
             return Cartesian3.multiplyByScalar(left, right, ScratchStorage.getCartesian3());
         } else if ((right instanceof Cartesian4) && (left instanceof Cartesian4)) {
             return Cartesian4.multiplyComponents(left, right, ScratchStorage.getCartesian4());
-        } else if ((right instanceof Cartesian4) && (typeof(left) === 'number')) {
+        } else if ((right instanceof Cartesian4) && (typeof left === 'number')) {
             return Cartesian4.multiplyByScalar(right, left, ScratchStorage.getCartesian4());
-        } else if ((left instanceof Cartesian4) && (typeof(right) === 'number')) {
+        } else if ((left instanceof Cartesian4) && (typeof right === 'number')) {
             return Cartesian4.multiplyByScalar(left, right, ScratchStorage.getCartesian4());
-        } else if ((typeof(left) === 'number') && (typeof(right) === 'number')) {
+        } else if ((typeof left === 'number') && (typeof right === 'number')) {
             return left * right;
         }
 
@@ -1226,17 +1226,17 @@ define([
         var right = this._right.evaluate(frameState, feature);
         if ((right instanceof Cartesian2) && (left instanceof Cartesian2)) {
             return Cartesian2.divideComponents(left, right, ScratchStorage.getCartesian2());
-        } else if ((left instanceof Cartesian2) && (typeof(right) === 'number')) {
+        } else if ((left instanceof Cartesian2) && (typeof right === 'number')) {
             return Cartesian2.divideByScalar(left, right, ScratchStorage.getCartesian2());
         } else if ((right instanceof Cartesian3) && (left instanceof Cartesian3)) {
             return Cartesian3.divideComponents(left, right, ScratchStorage.getCartesian3());
-        } else if ((left instanceof Cartesian3) && (typeof(right) === 'number')) {
+        } else if ((left instanceof Cartesian3) && (typeof right === 'number')) {
             return Cartesian3.divideByScalar(left, right, ScratchStorage.getCartesian3());
         } else if ((right instanceof Cartesian4) && (left instanceof Cartesian4)) {
             return Cartesian4.divideComponents(left, right, ScratchStorage.getCartesian4());
-        } else if ((left instanceof Cartesian4) && (typeof(right) === 'number')) {
+        } else if ((left instanceof Cartesian4) && (typeof right === 'number')) {
             return Cartesian4.divideByScalar(left, right, ScratchStorage.getCartesian4());
-        } else if ((typeof(left) === 'number') && (typeof(right) === 'number')) {
+        } else if ((typeof left === 'number') && (typeof right === 'number')) {
             return left / right;
         }
 
@@ -1256,7 +1256,7 @@ define([
             return Cartesian3.fromElements(left.x % right.x, left.y % right.y, left.z % right.z, ScratchStorage.getCartesian3());
         } else if ((right instanceof Cartesian4) && (left instanceof Cartesian4)) {
             return Cartesian4.fromElements(left.x % right.x, left.y % right.y, left.z % right.z, left.w % right.w, ScratchStorage.getCartesian4());
-        } else if ((typeof(left) === 'number') && (typeof(right) === 'number')) {
+        } else if ((typeof left === 'number') && (typeof right === 'number')) {
             return left % right;
         }
 

From e88310ab5d0b559822f429c0a855c96a30c943f7 Mon Sep 17 00:00:00 2001
From: Sean Lilley <lilleyse@gmail.com>
Date: Tue, 24 Jan 2017 12:30:12 -0500
Subject: [PATCH 2/7] Check type for conditional expression

---
 Source/Scene/Expression.js | 10 +++++++++-
 1 file changed, 9 insertions(+), 1 deletion(-)

diff --git a/Source/Scene/Expression.js b/Source/Scene/Expression.js
index ab9c0dd22fc..289899a73ec 100644
--- a/Source/Scene/Expression.js
+++ b/Source/Scene/Expression.js
@@ -1317,7 +1317,15 @@ define([
     };
 
     Node.prototype._evaluateConditional = function(frameState, feature) {
-        if (this._test.evaluate(frameState, feature)) {
+        var test = this._test.evaluate(frameState, feature);
+
+        //>>includeStart('debug', pragmas.debug);
+        if (typeof test !== 'boolean') {
+            throw new DeveloperError('First argument of conditional expression must be a boolean. Argument is ' + type + '.');
+        }
+        //>>includeEnd('debug');
+
+        if (test) {
             return this._left.evaluate(frameState, feature);
         }
         return this._right.evaluate(frameState, feature);

From 1eb5ad3107b57fc1713c4f7e2b2d3a0bda0ca463 Mon Sep 17 00:00:00 2001
From: Sean Lilley <lilleyse@gmail.com>
Date: Tue, 24 Jan 2017 16:35:02 -0500
Subject: [PATCH 3/7] Type checking for Regexp

---
 Source/Scene/Expression.js    | 48 ++++++++++++++++++-----
 Specs/Scene/ExpressionSpec.js | 71 ++++++++++++++++++++++++++++-------
 2 files changed, 95 insertions(+), 24 deletions(-)

diff --git a/Source/Scene/Expression.js b/Source/Scene/Expression.js
index 289899a73ec..411ac3627db 100644
--- a/Source/Scene/Expression.js
+++ b/Source/Scene/Expression.js
@@ -1383,35 +1383,63 @@ define([
     };
 
     Node.prototype._evaluateRegExpTest = function(frameState, feature) {
-        return this._left.evaluate(frameState, feature).test(this._right.evaluate(frameState, feature));
+        var left = this._left.evaluate(frameState, feature);
+        var right = this._right.evaluate(frameState, feature);
+
+        //>>includeStart('debug', pragmas.debug);
+        if (!((left instanceof RegExp) && (typeof right === 'string'))) {
+            throw new DeveloperError('RegExp.test requires the first argument to be a RegExp and the second argument to be a string. Arguments are ' + left + ' and ' + right + '.');
+        }
+        //>>includeEnd('debug');
+
+        return left.test(right);
     };
 
     Node.prototype._evaluateRegExpMatch = function(frameState, feature) {
         var left = this._left.evaluate(frameState, feature);
         var right = this._right.evaluate(frameState, feature);
-        if (left instanceof RegExp) {
+
+        if ((left instanceof RegExp) && (typeof right === 'string')) {
             return left.test(right);
-        } else if (right instanceof RegExp) {
+        } else if ((right instanceof RegExp) && (typeof left === 'string')) {
             return right.test(left);
-        } else {
-            return false;
         }
+
+        //>>includeStart('debug', pragmas.debug);
+        throw new DeveloperError('Operator "=~" requires one RegExp argument and one string argument. Arguments are ' + left + ' and ' + right + '.');
+        //>>includeEnd('debug');
+
+        return false; // jshint ignore:line
     };
 
     Node.prototype._evaluateRegExpNotMatch = function(frameState, feature) {
         var left = this._left.evaluate(frameState, feature);
         var right = this._right.evaluate(frameState, feature);
-        if (left instanceof RegExp) {
+
+        if ((left instanceof RegExp) && (typeof right === 'string')) {
             return !(left.test(right));
-        } else if (right instanceof RegExp) {
+        } else if ((right instanceof RegExp) && (typeof left === 'string')) {
             return !(right.test(left));
-        } else {
-            return false;
         }
+
+        //>>includeStart('debug', pragmas.debug);
+        throw new DeveloperError('Operator "!~" requires one RegExp argument and one string argument. Arguments are ' + left + ' and ' + right + '.');
+        //>>includeEnd('debug');
+
+        return false; // jshint ignore:line
     };
 
     Node.prototype._evaluateRegExpExec = function(frameState, feature) {
-        var exec = this._left.evaluate(frameState, feature).exec(this._right.evaluate(frameState, feature));
+        var left = this._left.evaluate(frameState, feature);
+        var right = this._right.evaluate(frameState, feature);
+
+        //>>includeStart('debug', pragmas.debug);
+        if (!((left instanceof RegExp) && (typeof right === 'string'))) {
+            throw new DeveloperError('RegExp.exec requires the first argument to be a RegExp and the second argument to be a string. Arguments are ' + left + ' and ' + right + '.');
+        }
+        //>>includeEnd('debug');
+
+        var exec = left.exec(right);
         if (!defined(exec)) {
             return null;
         }
diff --git a/Specs/Scene/ExpressionSpec.js b/Specs/Scene/ExpressionSpec.js
index 2ecb4a45338..8c7dd5cec32 100644
--- a/Specs/Scene/ExpressionSpec.js
+++ b/Specs/Scene/ExpressionSpec.js
@@ -2443,6 +2443,18 @@ defineSuite([
         expect(expression.evaluate(frameState, feature)).toEqual(true);
     });
 
+    it('throws if regex test function has invalid arguments', function() {
+        var expression = new Expression('regExp("1").test(1)');
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
+
+        expression = new Expression('regExp("a").test(regExp("b"))');
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
+    });
+
     it('evaluates regex exec function', function() {
         var feature = new MockFeature();
         feature.addProperty('property', 'abc');
@@ -2467,6 +2479,18 @@ defineSuite([
         expect(expression.evaluate(frameState, feature)).toEqual('1');
     });
 
+    it('throws if regex exec function has invalid arguments', function() {
+        var expression = new Expression('regExp("1").exec(1)');
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
+
+        expression = new Expression('regExp("a").exec(regExp("b"))');
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
+    });
+
     it('evaluates regex match operator', function() {
         var feature = new MockFeature();
         feature.addProperty('property', 'abc');
@@ -2486,17 +2510,28 @@ defineSuite([
         expression = new Expression('regExp("quick\\s(brown).+?(jumps)", "ig") =~ "The Quick Brown Fox Jumps Over The Lazy Dog"');
         expect(expression.evaluate(frameState, undefined)).toEqual(true);
 
-        expression = new Expression('regExp("a") =~ 1');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
+        expression = new Expression('regExp(${property}) =~ ${property}');
+        expect(expression.evaluate(frameState, feature)).toEqual(true);
+    });
+
+    it('throws if regex match operator has invalid arguments', function() {
+        var feature = new MockFeature();
+        feature.addProperty('property', 'abc');
+
+        var expression = new Expression('regExp("a") =~ 1');
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
 
         expression = new Expression('1 =~ regExp("a")');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
 
         expression = new Expression('1 =~ 1');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-
-        expression = new Expression('regExp(${property}) =~ ${property}');
-        expect(expression.evaluate(frameState, feature)).toEqual(true);
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
     });
 
     it('evaluates regex not match operator', function() {
@@ -2518,17 +2553,25 @@ defineSuite([
         expression = new Expression('regExp("quick\\s(brown).+?(jumps)", "ig") !~ "The Quick Brown Fox Jumps Over The Lazy Dog"');
         expect(expression.evaluate(frameState, undefined)).toEqual(false);
 
-        expression = new Expression('regExp("a") !~ 1');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
+        expression = new Expression('regExp(${property}) !~ ${property}');
+        expect(expression.evaluate(frameState, feature)).toEqual(false);
+    });
+
+    it('throws if regex not match operator has invalid arguments', function() {
+        var expression = new Expression('regExp("a") !~ 1');
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
 
         expression = new Expression('1 !~ regExp("a")');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
 
         expression = new Expression('1 !~ 1');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-
-        expression = new Expression('regExp(${property}) !~ ${property}');
-        expect(expression.evaluate(frameState, feature)).toEqual(false);
+        expect(function() {
+            expression.evaluate(frameState, undefined);
+        }).toThrowDeveloperError();
     });
 
     it('throws if test is not called with a RegExp', function() {

From 0a91e9bf411342568e3ec08fb1b7762b9e1bd300 Mon Sep 17 00:00:00 2001
From: Sean Lilley <lilleyse@gmail.com>
Date: Tue, 31 Jan 2017 16:17:34 -0500
Subject: [PATCH 4/7] Remove comments related to Matrix types in batch table
 binary

---
 Source/Scene/Cesium3DTileBatchTable.js  | 2 +-
 Source/Scene/PointCloud3DTileContent.js | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/Source/Scene/Cesium3DTileBatchTable.js b/Source/Scene/Cesium3DTileBatchTable.js
index 481d7140e59..ca76d975616 100644
--- a/Source/Scene/Cesium3DTileBatchTable.js
+++ b/Source/Scene/Cesium3DTileBatchTable.js
@@ -280,7 +280,7 @@ define([
                         }
 
                         // Store any information needed to access the binary data, including the typed array,
-                        // componentCount (e.g. a MAT4 would be 16), and the type used to pack and unpack (e.g. Matrix4).
+                        // componentCount (e.g. a VEC4 would be 4), and the type used to pack and unpack (e.g. Cartesian4).
                         binaryProperties[name] = {
                             typedArray : typedArray,
                             componentCount : componentCount,
diff --git a/Source/Scene/PointCloud3DTileContent.js b/Source/Scene/PointCloud3DTileContent.js
index a9404a5d887..60681f22a9a 100644
--- a/Source/Scene/PointCloud3DTileContent.js
+++ b/Source/Scene/PointCloud3DTileContent.js
@@ -506,7 +506,6 @@ define([
 
             for (var name in styleableProperties) {
                 if (styleableProperties.hasOwnProperty(name)) {
-                    // TODO : this will not handle matrix types currently
                     var property = styleableProperties[name];
                     var typedArray = property.typedArray;
                     var componentCount = property.componentCount;

From ed2970806741231a9cf1c4129a30a5ba0dd94f69 Mon Sep 17 00:00:00 2001
From: Sean Lilley <lilleyse@gmail.com>
Date: Tue, 31 Jan 2017 16:28:38 -0500
Subject: [PATCH 5/7] Remove == and !=

---
 .../gallery/3D Tiles Point Cloud Styling.html |  4 +-
 Apps/Sandcastle/gallery/3D Tiles.html         |  4 +-
 Source/Scene/ConditionsExpression.js          |  4 +-
 Source/Scene/Expression.js                    | 35 +---------
 Specs/Scene/Cesium3DTileStyleSpec.js          |  6 +-
 Specs/Scene/ConditionsExpressionSpec.js       |  2 +-
 Specs/Scene/ExpressionSpec.js                 | 70 +------------------
 7 files changed, 14 insertions(+), 111 deletions(-)

diff --git a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html
index 094c3bd3066..e3fbe386926 100644
--- a/Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html	
+++ b/Apps/Sandcastle/gallery/3D Tiles Point Cloud Styling.html	
@@ -98,11 +98,11 @@
 });
 
 addStyle('Show Subsections', {
-    show : "${id} == 1 || ${id} > 250 && ${id} < 300"
+    show : "${id} === 1 || ${id} > 250 && ${id} < 300"
 });
 
 addStyle('Mod', {
-    show : "${id} % 2 == 0"
+    show : "${id} % 2 === 0"
 });
 
 addStyle('Abs', {
diff --git a/Apps/Sandcastle/gallery/3D Tiles.html b/Apps/Sandcastle/gallery/3D Tiles.html
index e196a25295a..55a0f075e43 100644
--- a/Apps/Sandcastle/gallery/3D Tiles.html	
+++ b/Apps/Sandcastle/gallery/3D Tiles.html	
@@ -545,7 +545,7 @@
 
     var leftOperand = 0;
     var rightOperand = 0;
-    var op = '==';
+    var op = '===';
 
     // Left operand (properties and literals)
 
@@ -559,7 +559,7 @@
 
     // Operator
 
-    var ops = ['<', '<=', '>', '>=', '==', '!='];
+    var ops = ['<', '<=', '>', '>=', '===', '!=='];
     var operators = [{
         text : 'Operator',
         onselect : function() {
diff --git a/Source/Scene/ConditionsExpression.js b/Source/Scene/ConditionsExpression.js
index f25e2a95835..1b58f07af6d 100644
--- a/Source/Scene/ConditionsExpression.js
+++ b/Source/Scene/ConditionsExpression.js
@@ -33,8 +33,8 @@ define([
      * var expression = new Cesium.Expression({
      *     expression : 'regExp("^1(\\d)").exec(${id})',
      *     conditions : [
-     *         ['${expression} == "1"', 'color("#FF0000")'],
-     *         ['${expression} == "2"', 'color("#00FF00")'],
+     *         ['${expression} === "1"', 'color("#FF0000")'],
+     *         ['${expression} === "2"', 'color("#00FF00")'],
      *         ['true', 'color("#FFFFFF")']
      *     ]
      * });
diff --git a/Source/Scene/Expression.js b/Source/Scene/Expression.js
index 411ac3627db..cf4ea330aa6 100644
--- a/Source/Scene/Expression.js
+++ b/Source/Scene/Expression.js
@@ -26,7 +26,7 @@ define([
     "use strict";
 
     var unaryOperators = ['!', '-', '+'];
-    var binaryOperators = ['+', '-', '*', '/', '%', '===', '==', '!==', '!=', '>', '>=', '<', '<=', '&&', '||', '!~', '=~'];
+    var binaryOperators = ['+', '-', '*', '/', '%', '===', '!==', '>', '>=', '<', '<=', '&&', '||', '!~', '=~'];
 
     var variableRegex = /\${(.*?)}/g;
     var backslashRegex = /\\/g;
@@ -713,12 +713,8 @@ define([
                 node.evaluate = node._evaluateMod;
             } else if (node._value === '===') {
                 node.evaluate = node._evaluateEqualsStrict;
-            } else if (node._value === '==') {
-                node.evaluate = node._evaluateEquals;
             } else if (node._value === '!==') {
                 node.evaluate = node._evaluateNotEqualsStrict;
-            } else if (node._value === '!=') {
-                node.evaluate = node._evaluateNotEquals;
             } else if (node._value === '<') {
                 node.evaluate = node._evaluateLessThan;
             } else if (node._value === '<=') {
@@ -1278,20 +1274,6 @@ define([
         return left === right;
     };
 
-    Node.prototype._evaluateEquals = function(frameState, feature) {
-        var left = this._left.evaluate(frameState, feature);
-        var right = this._right.evaluate(frameState, feature);
-        if ((right instanceof Cartesian2) && (left instanceof Cartesian2) ||
-            (right instanceof Cartesian3) && (left instanceof Cartesian3) ||
-            (right instanceof Cartesian4) && (left instanceof Cartesian4)) {
-            return left.equals(right);
-        }
-
-        // Specifically want to do an abstract equality comparison (==) instead of a strict equality comparison (===)
-        // so that cases like "5 == '5'" return true. Tell jsHint to ignore this line.
-        return left == right; // jshint ignore:line
-    };
-
     Node.prototype._evaluateNotEqualsStrict = function(frameState, feature) {
         var left = this._left.evaluate(frameState, feature);
         var right = this._right.evaluate(frameState, feature);
@@ -1303,19 +1285,6 @@ define([
         return left !== right;
     };
 
-    Node.prototype._evaluateNotEquals = function(frameState, feature) {
-        var left = this._left.evaluate(frameState, feature);
-        var right = this._right.evaluate(frameState, feature);
-        if ((right instanceof Cartesian2) && (left instanceof Cartesian2) ||
-            (right instanceof Cartesian3) && (left instanceof Cartesian3) ||
-            (right instanceof Cartesian4) && (left instanceof Cartesian4)) {
-            return !left.equals(right);
-        }
-        // Specifically want to do an abstract inequality comparison (!=) instead of a strict inequality comparison (!==)
-        // so that cases like "5 != '5'" return false. Tell jsHint to ignore this line.
-        return left != right; // jshint ignore:line
-    };
-
     Node.prototype._evaluateConditional = function(frameState, feature) {
         var test = this._test.evaluate(frameState, feature);
 
@@ -1602,7 +1571,7 @@ define([
                 }
                 return value + left;
             case ExpressionNodeType.BINARY:
-                // Supported types: ||, &&, ===, ==, !==, !=, <, >, <=, >=, +, -, *, /, %
+                // Supported types: ||, &&, ===, !==, <, >, <=, >=, +, -, *, /, %
                 if (value === '%') {
                     return 'mod(' + left + ', ' + right + ')';
                 } else if (value === '===') {
diff --git a/Specs/Scene/Cesium3DTileStyleSpec.js b/Specs/Scene/Cesium3DTileStyleSpec.js
index c4d4d4adc20..8d4a09bc869 100644
--- a/Specs/Scene/Cesium3DTileStyleSpec.js
+++ b/Specs/Scene/Cesium3DTileStyleSpec.js
@@ -330,7 +330,7 @@ defineSuite([
 
     it('applies show style with variable', function() {
         var style = new Cesium3DTileStyle({
-            "show" : "${ZipCode} == '19341'"
+            "show" : "${ZipCode} === '19341'"
         });
 
         expect(style.show.evaluate(frameState, feature1)).toEqual(true);
@@ -406,8 +406,8 @@ defineSuite([
             "color" : {
                 "expression" : "regExp('^1(\\d)').exec(${id})",
                 "conditions" : [
-                    ["${expression} == '1'", "color('#FF0000')"],
-                    ["${expression} == '2'", "color('#00FF00')"],
+                    ["${expression} === '1'", "color('#FF0000')"],
+                    ["${expression} === '2'", "color('#00FF00')"],
                     ["true", "color('#FFFFFF')"]
                 ]
             }
diff --git a/Specs/Scene/ConditionsExpressionSpec.js b/Specs/Scene/ConditionsExpressionSpec.js
index 4bc58500ff7..9f636da4959 100644
--- a/Specs/Scene/ConditionsExpressionSpec.js
+++ b/Specs/Scene/ConditionsExpressionSpec.js
@@ -48,7 +48,7 @@ defineSuite([
 
     var jsonExpWithUndefinedExpression = {
         conditions : [
-            ['${expression} == undefined', 'color("blue")'],
+            ['${expression} === undefined', 'color("blue")'],
             ['true', 'color("lime")']
         ]
     };
diff --git a/Specs/Scene/ExpressionSpec.js b/Specs/Scene/ExpressionSpec.js
index 8c7dd5cec32..26219853c55 100644
--- a/Specs/Scene/ExpressionSpec.js
+++ b/Specs/Scene/ExpressionSpec.js
@@ -1010,20 +1010,6 @@ defineSuite([
         expect(expression.evaluate(frameState, undefined)).toEqual(false);
     });
 
-    it('evaluates binary equals', function() {
-        var expression = new Expression('\'hello\' == \'hello\'');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-
-        expression = new Expression('1 == 2');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-
-        expression = new Expression('false == true == false');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-
-        expression = new Expression('1 == "1"');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-    });
-
     it('evaluates binary not equals strict', function() {
         var expression = new Expression('\'hello\' !== \'hello\'');
         expect(expression.evaluate(frameState, undefined)).toEqual(false);
@@ -1038,20 +1024,6 @@ defineSuite([
         expect(expression.evaluate(frameState, undefined)).toEqual(true);
     });
 
-    it('evaluates binary not equals', function() {
-        var expression = new Expression('\'hello\' != \'hello\'');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-
-        expression = new Expression('1 != 2');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-
-        expression = new Expression('false != true != false');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-
-        expression = new Expression('1 != "1"');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-    });
-
     it('evaluates binary less than', function() {
         var expression = new Expression('2 < 3');
         expect(expression.evaluate(frameState, undefined)).toEqual(true);
@@ -1278,15 +1250,9 @@ defineSuite([
         expression = new Expression('rgba(255, 255, 255, 1.0) % rgba(255, 255, 255, 1.0)');
         expect(expression.evaluate(frameState, undefined)).toEqual(Cartesian4.fromColor(new Color(0, 0, 0, 0)));
 
-        expression = new Expression('color(\'green\') == color(\'green\')');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-
-        expression = new Expression('color() == color()');
+        expression = new Expression('color(\'green\') === color(\'green\')');
         expect(expression.evaluate(frameState, undefined)).toEqual(true);
 
-        expression = new Expression('color(\'green\') != color(\'green\')');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-
         expression = new Expression('color(\'green\') !== color(\'green\')');
         expect(expression.evaluate(frameState, undefined)).toEqual(false);
     });
@@ -1382,15 +1348,6 @@ defineSuite([
         expression = new Expression('vec4(2, 3, 4, 5) % vec4(3, 3, 3, 2)');
         expect(expression.evaluate(frameState, undefined)).toEqual(new Cartesian4(2, 0, 1, 1));
 
-        expression = new Expression('vec2(1, 3) == vec2(1, 3)');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-
-        expression = new Expression('vec3(1, 3, 4) == vec3(1, 3, 4)');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-
-        expression = new Expression('vec4(1, 3, 4, 6) == vec4(1, 3, 4, 6)');
-        expect(expression.evaluate(frameState, undefined)).toEqual(true);
-
         expression = new Expression('vec2(1, 2) === vec2(1, 2)');
         expect(expression.evaluate(frameState, undefined)).toEqual(true);
 
@@ -1400,15 +1357,6 @@ defineSuite([
         expression = new Expression('vec4(1, 2, 3, 4) === vec4(1, 2, 3, 4)');
         expect(expression.evaluate(frameState, undefined)).toEqual(true);
 
-        expression = new Expression('vec2(1, 2) != vec2(1, 2)');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-
-        expression = new Expression('vec3(1, 2, 3) != vec3(1, 2, 3)');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-
-        expression = new Expression('vec4(1, 2, 3, 4) != vec4(1, 2, 3, 4)');
-        expect(expression.evaluate(frameState, undefined)).toEqual(false);
-
         expression = new Expression('vec2(1, 2) !== vec2(1, 2)');
         expect(expression.evaluate(frameState, undefined)).toEqual(false);
 
@@ -2358,7 +2306,7 @@ defineSuite([
             vector : Cartesian4.UNIT_X
         });
 
-        expression = new Expression('${feature} == ${feature.feature}');
+        expression = new Expression('${feature} === ${feature.feature}');
         expect(expression.evaluate(frameState, feature)).toEqual(true);
     });
 
@@ -2751,13 +2699,6 @@ defineSuite([
         expect(shaderExpression).toEqual(expected);
     });
 
-    it('gets shader expression for binary equals', function() {
-        var expression = new Expression('1.0 == 2.0');
-        var shaderExpression = expression.getShaderExpression('', {});
-        var expected = '(1.0 == 2.0)';
-        expect(shaderExpression).toEqual(expected);
-    });
-
     it('gets shader expression for binary not equals strict', function() {
         var expression = new Expression('1.0 !== 2.0');
         var shaderExpression = expression.getShaderExpression('', {});
@@ -2765,13 +2706,6 @@ defineSuite([
         expect(shaderExpression).toEqual(expected);
     });
 
-    it('gets shader expression for binary not equals', function() {
-        var expression = new Expression('1.0 != 2.0');
-        var shaderExpression = expression.getShaderExpression('', {});
-        var expected = '(1.0 != 2.0)';
-        expect(shaderExpression).toEqual(expected);
-    });
-
     it('gets shader expression for binary less than', function() {
         var expression = new Expression('1.0 < 2.0');
         var shaderExpression = expression.getShaderExpression('', {});

From 360ffd007fc43b64ac0029c6bfcca66cabe942a2 Mon Sep 17 00:00:00 2001
From: Sean Lilley <lilleyse@gmail.com>
Date: Tue, 31 Jan 2017 17:16:15 -0500
Subject: [PATCH 6/7] Fix test

---
 Specs/Scene/Cesium3DTileStyleSpec.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Specs/Scene/Cesium3DTileStyleSpec.js b/Specs/Scene/Cesium3DTileStyleSpec.js
index 8d4a09bc869..b553b8a063a 100644
--- a/Specs/Scene/Cesium3DTileStyleSpec.js
+++ b/Specs/Scene/Cesium3DTileStyleSpec.js
@@ -404,7 +404,7 @@ defineSuite([
     it('applies color style that maps id to color', function() {
         var style = new Cesium3DTileStyle({
             "color" : {
-                "expression" : "regExp('^1(\\d)').exec(${id})",
+                "expression" : "regExp('^1(\\d)').exec(String(${id}))",
                 "conditions" : [
                     ["${expression} === '1'", "color('#FF0000')"],
                     ["${expression} === '2'", "color('#00FF00')"],

From 57e67f17e4262386f3a9d1afca02199a1f719e22 Mon Sep 17 00:00:00 2001
From: Sean Lilley <lilleyse@gmail.com>
Date: Tue, 31 Jan 2017 17:24:46 -0500
Subject: [PATCH 7/7] Fix jsHint

---
 Source/Scene/Expression.js | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/Source/Scene/Expression.js b/Source/Scene/Expression.js
index cf4ea330aa6..659797fa523 100644
--- a/Source/Scene/Expression.js
+++ b/Source/Scene/Expression.js
@@ -1290,7 +1290,7 @@ define([
 
         //>>includeStart('debug', pragmas.debug);
         if (typeof test !== 'boolean') {
-            throw new DeveloperError('First argument of conditional expression must be a boolean. Argument is ' + type + '.');
+            throw new DeveloperError('Conditional argument of conditional expression must be a boolean. Argument is ' + test + '.');
         }
         //>>includeEnd('debug');