Skip to content

Commit

Permalink
Check for type mismatch in JS and shader backends
Browse files Browse the repository at this point in the history
  • Loading branch information
lilleyse committed Jan 12, 2017
1 parent 70e841b commit 4967e71
Show file tree
Hide file tree
Showing 2 changed files with 104 additions and 10 deletions.
101 changes: 91 additions & 10 deletions Source/Scene/Expression.js
Original file line number Diff line number Diff line change
Expand Up @@ -960,7 +960,13 @@ define([
// that we can assign if we know the types before runtime

Node.prototype._evaluateNot = function(frameState, feature) {
return !(this._left.evaluate(frameState, feature));
var left = this._left.evaluate(frameState, feature);
//>>includeStart('debug', pragmas.debug);
if (typeof(left) !== 'boolean') {
throw new DeveloperError('Error: Operation is undefined.');
}
//>>includeEnd('debug');
return !left;
};

Node.prototype._evaluateNegative = function(frameState, feature) {
Expand All @@ -971,39 +977,77 @@ define([
return Cartesian3.negate(left, ScratchStorage.getCartesian3());
} else if (left instanceof Cartesian4) {
return Cartesian4.negate(left, ScratchStorage.getCartesian4());
} else if (typeof(left) === 'number') {
return -left;
}
return -left;

//>>includeStart('debug', pragmas.debug);
throw new DeveloperError('Error: Operation is undefined.');
//>>includeEnd('debug');
return -left; // jshint ignore:line
};

Node.prototype._evaluatePositive = function(frameState, feature) {
var left = this._left.evaluate(frameState, feature);
if ((left instanceof Cartesian2) || (left instanceof Cartesian3) || (left instanceof Cartesian4)) {
return left;

//>>includeStart('debug', pragmas.debug);
if (!((left instanceof Cartesian2) || (left instanceof Cartesian3) || (left instanceof Cartesian4) || (typeof(left) === 'number'))) {
throw new DeveloperError('Error: Operation is undefined.');
}
return +left;
//>>includeEnd('debug');

return left;
};

Node.prototype._evaluateLessThan = function(frameState, feature) {
var left = this._left.evaluate(frameState, feature);
var right = this._right.evaluate(frameState, feature);

//>>includeStart('debug', pragmas.debug);
if ((typeof(left) !== 'number') || (typeof(right) !== 'number')) {
throw new DeveloperError('Error: Operation is undefined.');
}
//>>includeEnd('debug');

return left < right;
};

Node.prototype._evaluateLessThanOrEquals = function(frameState, feature) {
var left = this._left.evaluate(frameState, feature);
var right = this._right.evaluate(frameState, feature);

//>>includeStart('debug', pragmas.debug);
if ((typeof(left) !== 'number') || (typeof(right) !== 'number')) {
throw new DeveloperError('Error: Operation is undefined.');
}
//>>includeEnd('debug');

return left <= right;
};

Node.prototype._evaluateGreaterThan = function(frameState, feature) {
var left = this._left.evaluate(frameState, feature);
var right = this._right.evaluate(frameState, feature);

//>>includeStart('debug', pragmas.debug);
if ((typeof(left) !== 'number') || (typeof(right) !== 'number')) {
throw new DeveloperError('Error: Operation is undefined.');
}
//>>includeEnd('debug');

return left > right;
};

Node.prototype._evaluateGreaterThanOrEquals = function(frameState, feature) {
var left = this._left.evaluate(frameState, feature);
var right = this._right.evaluate(frameState, feature);

//>>includeStart('debug', pragmas.debug);
if ((typeof(left) !== 'number') || (typeof(right) !== 'number')) {
throw new DeveloperError('Error: Operation is undefined.');
}
//>>includeEnd('debug');

return left >= right;
};

Expand Down Expand Up @@ -1060,8 +1104,17 @@ 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')) {
return left + right;
} else if ((typeof(left) === 'number') && (typeof(right) === 'number')) {
return left + right;
}
return left + right;

//>>includeStart('debug', pragmas.debug);
throw new DeveloperError('Error: Operation is undefined.');
//>>includeEnd('debug');

return left + right; // jshint ignore:line
};

Node.prototype._evaluateMinus = function(frameState, feature) {
Expand All @@ -1073,8 +1126,15 @@ 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')) {
return left - right;
}
return left - right;

//>>includeStart('debug', pragmas.debug);
throw new DeveloperError('Error: Operation is undefined.');
//>>includeEnd('debug');

return left - right; // jshint ignore:line
};

Node.prototype._evaluateTimes = function(frameState, feature) {
Expand All @@ -1098,8 +1158,15 @@ define([
return Cartesian4.multiplyByScalar(right, left, ScratchStorage.getCartesian4());
} else if ((left instanceof Cartesian4) && (typeof(right) === 'number')) {
return Cartesian4.multiplyByScalar(left, right, ScratchStorage.getCartesian4());
} else if ((typeof(left) === 'number') && (typeof(right) === 'number')) {
return left * right;
}
return left * right;

//>>includeStart('debug', pragmas.debug);
throw new DeveloperError('Error: Operation is undefined.');
//>>includeEnd('debug');

return left * right; // jshint ignore:line
};

Node.prototype._evaluateDivide = function(frameState, feature) {
Expand All @@ -1117,8 +1184,15 @@ define([
return Cartesian4.divideComponents(left, right, ScratchStorage.getCartesian4());
} else if ((left instanceof Cartesian4) && (typeof(right) === 'number')) {
return Cartesian4.divideByScalar(left, right, ScratchStorage.getCartesian4());
} else if ((typeof(left) === 'number') && (typeof(right) === 'number')) {
return left / right;
}
return left / right;

//>>includeStart('debug', pragmas.debug);
throw new DeveloperError('Error: Operation is undefined.');
//>>includeEnd('debug');

return left / right; // jshint ignore:line
};

Node.prototype._evaluateMod = function(frameState, feature) {
Expand All @@ -1130,8 +1204,15 @@ 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')) {
return left % right;
}
return left % right;

//>>includeStart('debug', pragmas.debug);
throw new DeveloperError('Error: Operation is undefined.');
//>>includeEnd('debug');

return left % right; // jshint ignore:line
};

Node.prototype._evaluateEqualsStrict = function(frameState, feature) {
Expand Down
13 changes: 13 additions & 0 deletions Source/Scene/PointCloud3DTileContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,19 @@ define([
fragmentShaderSource : pickFS,
attributeLocations : attributeLocations
});

try {
// Check if the shader compiles correctly. If not there is likely a syntax error with the style.
drawCommand.shaderProgram._bind();
} catch (error) {
//>>includeStart('debug', pragmas.debug);
// Turn the RuntimeError into a DeveloperError and rephrase it.
throw new DeveloperError('Error generating style shader: this may be caused by a type mismatch, index out-of-bounds, or other syntax error.');
//>>includeEnd('debug');

// In release silently ignore and recreate the shader without a style. Tell jsHint to ignore this line.
createShaders(content, frameState, undefined); // jshint ignore:line
}
}

/**
Expand Down

0 comments on commit 4967e71

Please sign in to comment.