Fix type conversion in calculation constructed by CSS typed OM

Current implementation of CSSMathFunctionValue assumes a simplified
expression node tree, where some units are already canonicalized (e.g.,
angle units are canonicalized into 'deg'). This doesn't hold if the
tree is constructed by CSS typed OM.

This patch fixes the issue by introducing a safe API
CSSMathExpressionNode::ComputeValueInCanonicalUnit(), which evaluates
the expression and handles type conversions, and in case of failure,
returns nullopt.

Bug: 983702
Change-Id: Ib8d5be3731b4b6585913223f11cdd3656eefb486
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1700356
Reviewed-by: Anders Hartvoll Ruud <andruud@chromium.org>
Commit-Queue: Xiaocheng Hu <xiaochengh@chromium.org>
Cr-Commit-Position: refs/heads/master@{#678594}
diff --git a/css/css-typed-om/rotate-by-added-angle-ref.html b/css/css-typed-om/rotate-by-added-angle-ref.html
new file mode 100644
index 0000000..36c18d8
--- /dev/null
+++ b/css/css-typed-om/rotate-by-added-angle-ref.html
@@ -0,0 +1,17 @@
+<!DOCTYPE html>
+<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-typed-om-1/#stylevalue-subclasses">
+<meta name="assert" content="CSSUnitValue of different angle units can be added correctly.">
+<style>
+.ref {
+  width: 200px;
+  height: 100px;
+  position: absolute;
+  top: 100px;
+  left: 100px;
+  transform: rotate(90deg);
+  background-color: green;
+}
+</style>
+<p>Test passes if there is a filled green rectangle with <strong>no red</strong>.</p>
+<div class="ref"></div>
diff --git a/css/css-typed-om/rotate-by-added-angle.html b/css/css-typed-om/rotate-by-added-angle.html
new file mode 100644
index 0000000..bb79a7d
--- /dev/null
+++ b/css/css-typed-om/rotate-by-added-angle.html
@@ -0,0 +1,31 @@
+<!DOCTYPE html>
+<link rel="author" title="Xiaocheng Hu" href="mailto:xiaochengh@chromium.org">
+<link rel="help" href="https://www.w3.org/TR/css-typed-om-1/#stylevalue-subclasses">
+<link rel="match" href="rotate-by-added-angle-ref.html">
+<meta name="assert" content="CSSUnitValue of different angle units can be added correctly.">
+<style>
+.common {
+  width: 200px;
+  height: 100px;
+  position: absolute;
+  top: 100px;
+  left: 100px;
+}
+.ref {
+  transform: rotate(90deg);
+  background-color: red;
+}
+.test {
+  background-color: green;
+  z-index: 1;
+}
+</style>
+<p>Test passes if there is a filled green rectangle with <strong>no red</strong>.</p>
+<div class="common ref"></div>
+<div class="common test"></div>
+<script>
+const angle = new CSSMathSum(CSS.deg(45), CSS.turn(0.125)); // 90 degrees
+const transform = new CSSTransformValue([new CSSRotate(angle)]);
+const target = document.querySelector('.test');
+target.attributeStyleMap.set('transform', transform);
+</script>