Repository: robertkrimen/otto
Pull request #485 (2023-01-11 15:33:53)

feat:add math function
add some math function
- Math.acosh
- Math.asinh
- Math.atanh
- Math.cbrt
- Math.cosh
- Math.expm1
- Math.log10
- Math.log1p
- Math.log2
- Math.sinh
- Math.tanh
- Math.trunc

noobHuKai: Don't from Edition 5.1, but from [Edition 6.0](https://262.ecma-international.org/6.0/#sec-function-properties-of-the-math-object)
These math function are common


Asday: Common as you want:

> * Otto targets ES5. ES6 features (eg: Typed Arrays) are not supported.

-- https://github.com/robertkrimen/otto#caveat-emptor
stevenh: Lets try an move that forward :)
stevenh: @noobHuKai as you can see from [failure](https://github.com/robertkrimen/otto/actions/runs/3894272524/jobs/6666156842) `inline.go` is auto generated by [tools/gen-jscore](https://github.com/robertkrimen/otto/tree/master/tools/gen-jscore) so you will need update to its [configuration](https://github.com/robertkrimen/otto/blob/master/tools/gen-jscore/.gen-jscore.yaml) to ensure that's compatible.

Patch:
diff --git a/builtin_math.go b/builtin_math.go
index 1774fd8..ac62d8c 100644
--- a/builtin_math.go
+++ b/builtin_math.go
@@ -17,11 +17,21 @@ func builtinMathAcos(call FunctionCall) Value {
 	return float64Value(math.Acos(number))
 }
 
+func builtinMathAcosh(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Acosh(number))
+}
+
 func builtinMathAsin(call FunctionCall) Value {
 	number := call.Argument(0).float64()
 	return float64Value(math.Asin(number))
 }
 
+func builtinMathAsinh(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Asinh(number))
+}
+
 func builtinMathAtan(call FunctionCall) Value {
 	number := call.Argument(0).float64()
 	return float64Value(math.Atan(number))
@@ -39,6 +49,16 @@ func builtinMathAtan2(call FunctionCall) Value {
 	return float64Value(math.Atan2(y, x))
 }
 
+func builtinMathAtanh(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Atanh(number))
+}
+
+func builtinMathCbrt(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Cbrt(number))
+}
+
 func builtinMathCos(call FunctionCall) Value {
 	number := call.Argument(0).float64()
 	return float64Value(math.Cos(number))
@@ -49,11 +69,21 @@ func builtinMathCeil(call FunctionCall) Value {
 	return float64Value(math.Ceil(number))
 }
 
+func builtinMathCosh(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Cosh(number))
+}
+
 func builtinMathExp(call FunctionCall) Value {
 	number := call.Argument(0).float64()
 	return float64Value(math.Exp(number))
 }
 
+func builtinMathExpm1(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Expm1(number))
+}
+
 func builtinMathFloor(call FunctionCall) Value {
 	number := call.Argument(0).float64()
 	return float64Value(math.Floor(number))
@@ -64,6 +94,21 @@ func builtinMathLog(call FunctionCall) Value {
 	return float64Value(math.Log(number))
 }
 
+func builtinMathLog10(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Log10(number))
+}
+
+func builtinMathLog1p(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Log1p(number))
+}
+
+func builtinMathLog2(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Log2(number))
+}
+
 func builtinMathMax(call FunctionCall) Value {
 	switch len(call.ArgumentList) {
 	case 0:
@@ -140,6 +185,11 @@ func builtinMathSin(call FunctionCall) Value {
 	return float64Value(math.Sin(number))
 }
 
+func builtinMathSinh(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Sinh(number))
+}
+
 func builtinMathSqrt(call FunctionCall) Value {
 	number := call.Argument(0).float64()
 	return float64Value(math.Sqrt(number))
@@ -149,3 +199,13 @@ func builtinMathTan(call FunctionCall) Value {
 	number := call.Argument(0).float64()
 	return float64Value(math.Tan(number))
 }
+
+func builtinMathTanh(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Tanh(number))
+}
+
+func builtinMathTrunc(call FunctionCall) Value {
+	number := call.Argument(0).float64()
+	return float64Value(math.Trunc(number))
+}
diff --git a/inline.go b/inline.go
index 5f563f8..778a5d0 100644
--- a/inline.go
+++ b/inline.go
@@ -1,3 +1,5 @@
+// Code generated by tools/gen-jscore. DO NOT EDIT.
+
 package otto
 
 import (
@@ -3431,6 +3433,43 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"acosh": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "acosh",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "acosh",
+							call: builtinMathAcosh,
+						},
+					},
+				},
+			},
 			"asin": {
 				mode: 0o101,
 				value: Value{
@@ -3468,6 +3507,43 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"asinh": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "asinh",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "asinh",
+							call: builtinMathAsinh,
+						},
+					},
+				},
+			},
 			"atan": {
 				mode: 0o101,
 				value: Value{
@@ -3505,6 +3581,43 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"atanh": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "atanh",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "atanh",
+							call: builtinMathAtanh,
+						},
+					},
+				},
+			},
 			"atan2": {
 				mode: 0o101,
 				value: Value{
@@ -3542,6 +3655,43 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"cbrt": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "cbrt",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "cbrt",
+							call: builtinMathCbrt,
+						},
+					},
+				},
+			},
 			"ceil": {
 				mode: 0o101,
 				value: Value{
@@ -3616,6 +3766,43 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"cosh": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "cosh",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "cosh",
+							call: builtinMathCosh,
+						},
+					},
+				},
+			},
 			"exp": {
 				mode: 0o101,
 				value: Value{
@@ -3653,6 +3840,43 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"expm1": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "expm1",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "expm1",
+							call: builtinMathExpm1,
+						},
+					},
+				},
+			},
 			"floor": {
 				mode: 0o101,
 				value: Value{
@@ -3727,6 +3951,117 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"log10": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "log10",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "log10",
+							call: builtinMathLog10,
+						},
+					},
+				},
+			},
+			"log1p": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "log1p",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "log1p",
+							call: builtinMathLog1p,
+						},
+					},
+				},
+			},
+			"log2": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "log2",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "log2",
+							call: builtinMathLog2,
+						},
+					},
+				},
+			},
 			"max": {
 				mode: 0o101,
 				value: Value{
@@ -3949,6 +4284,43 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"sinh": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "sinh",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "sinh",
+							call: builtinMathSinh,
+						},
+					},
+				},
+			},
 			"sqrt": {
 				mode: 0o101,
 				value: Value{
@@ -4023,6 +4395,80 @@ func (rt *runtime) newContext() {
 					},
 				},
 			},
+			"tanh": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "tanh",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "tanh",
+							call: builtinMathTanh,
+						},
+					},
+				},
+			},
+			"trunc": {
+				mode: 0o101,
+				value: Value{
+					kind: valueObject,
+					value: &object{
+						runtime:     rt,
+						class:       classFunctionName,
+						objectClass: classObject,
+						prototype:   rt.global.FunctionPrototype,
+						extensible:  true,
+						property: map[string]property{
+							propertyLength: {
+								mode: 0,
+								value: Value{
+									kind:  valueNumber,
+									value: 1,
+								},
+							},
+							propertyName: {
+								mode: 0,
+								value: Value{
+									kind:  valueString,
+									value: "trunc",
+								},
+							},
+						},
+						propertyOrder: []string{
+							propertyLength,
+							propertyName,
+						},
+						value: nativeFunctionObject{
+							name: "trunc",
+							call: builtinMathTrunc,
+						},
+					},
+				},
+			},
 			"E": {
 				mode: 0,
 				value: Value{
@@ -4083,22 +4529,34 @@ func (rt *runtime) newContext() {
 		propertyOrder: []string{
 			"abs",
 			"acos",
+			"acosh",
 			"asin",
+			"asinh",
 			"atan",
+			"atanh",
 			"atan2",
+			"cbrt",
 			"ceil",
 			"cos",
+			"cosh",
 			"exp",
+			"expm1",
 			"floor",
 			"log",
+			"log10",
+			"log1p",
+			"log2",
 			"max",
 			"min",
 			"pow",
 			"random",
 			"round",
 			"sin",
+			"sinh",
 			"sqrt",
 			"tan",
+			"tanh",
+			"trunc",
 			"E",
 			"LN10",
 			"LN2",
diff --git a/token/token_const.go b/token/token_const.go
index a3e56f5..09ba017 100644
--- a/token/token_const.go
+++ b/token/token_const.go
@@ -1,3 +1,5 @@
+// Code generated by tools/gen-tokens. DO NOT EDIT.
+
 package token
 
 const (
diff --git a/tools/gen-jscore/.gen-jscore.yaml b/tools/gen-jscore/.gen-jscore.yaml
index a3f30fe..a4d9677 100644
--- a/tools/gen-jscore/.gen-jscore.yaml
+++ b/tools/gen-jscore/.gen-jscore.yaml
@@ -272,22 +272,40 @@ types:
           function: 1
         - name: acos
           function: 1
+        - name: acosh
+          function: 1
         - name: asin
           function: 1
+        - name: asinh
+          function: 1
         - name: atan
           function: 1
+        - name: atanh
+          function: 1
         - name: atan2
           function: 1
+        - name: cbrt
+          function: 1
         - name: ceil
           function: 1
         - name: cos
           function: 1
+        - name: cosh
+          function: 1
         - name: exp
           function: 1
+        - name: expm1
+          function: 1
         - name: floor
           function: 1
         - name: log
           function: 1
+        - name: log10
+          function: 1
+        - name: log1p
+          function: 1
+        - name: log2
+          function: 1
         - name: max
           function: 2
         - name: min
@@ -300,10 +318,16 @@ types:
           function: 1
         - name: sin
           function: 1
+        - name: sinh
+          function: 1
         - name: sqrt
           function: 1
         - name: tan
           function: 1
+        - name: tanh
+          function: 1
+        - name: trunc
+          function: 1
         - name: E
           kind: valueNumber
           value: math.E
diff --git a/tools/gen-jscore/templates/root.tmpl b/tools/gen-jscore/templates/root.tmpl
index 1951fbd..5878967 100644
--- a/tools/gen-jscore/templates/root.tmpl
+++ b/tools/gen-jscore/templates/root.tmpl
@@ -1,3 +1,5 @@
+// Code generated by tools/gen-jscore. DO NOT EDIT.
+
 package otto
 
 import (
diff --git a/tools/gen-tokens/templates/root.tmpl b/tools/gen-tokens/templates/root.tmpl
index 86e49fb..6b2d9cc 100644
--- a/tools/gen-tokens/templates/root.tmpl
+++ b/tools/gen-tokens/templates/root.tmpl
@@ -1,3 +1,5 @@
+// Code generated by tools/gen-tokens. DO NOT EDIT.
+
 package token
 
 const (


Test patch:
diff --git a/inline_test.go b/inline_test.go
index 57277ef..062d1e8 100644
--- a/inline_test.go
+++ b/inline_test.go
@@ -132,27 +132,27 @@ func TestGetOwnPropertyNames(t *testing.T) {
 		"Math": {
 			"abs",
 			"acos",
-			// "acosh",
+			"acosh",
 			"asin",
-			// "asinh",
+			"asinh",
 			"atan",
-			// "atanh",
+			"atanh",
 			"atan2",
+			"cbrt",
 			"ceil",
-			// "cbrt",
-			// "expm1",
 			// "clz32",
 			"cos",
-			// "cosh",
+			"cosh",
 			"exp",
+			"expm1",
 			"floor",
 			// "fround",
 			// "hypot",
 			// "imul",
 			"log",
-			// "log1p",
-			// "log2",
-			// "log10",
+			"log10",
+			"log1p",
+			"log2",
 			"max",
 			"min",
 			"pow",
@@ -160,11 +160,11 @@ func TestGetOwnPropertyNames(t *testing.T) {
 			"round",
 			// "sign",
 			"sin",
-			// "sinh",
+			"sinh",
 			"sqrt",
 			"tan",
-			// "tanh",
-			// "trunc",
+			"tanh",
+			"trunc",
 			"E",
 			"LN10",
 			"LN2",
diff --git a/math_test.go b/math_test.go
index 49b3388..1a4cd9b 100644
--- a/math_test.go
+++ b/math_test.go
@@ -50,6 +50,20 @@ func TestMath_acos(t *testing.T) {
 	})
 }
 
+func TestMath_acosh(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.acosh(-1)`, naN)
+		test(`Math.acosh(0)`, naN)
+		test(`Math.acosh(0.999999999999)`, naN)
+		test(`1/Math.acosh(1)`, infinity)
+		test(`Math.acosh(Infinity)`, infinity)
+		test(`Math.acosh(2)`, 1.3169578969248166)
+		test(`Math.acosh(2.5)`, 1.566799236972411)
+	})
+}
+
 func TestMath_asin(t *testing.T) {
 	tt(t, func() {
 		test, _ := test()
@@ -64,6 +78,20 @@ func TestMath_asin(t *testing.T) {
 	})
 }
 
+func TestMath_asinh(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.asinh(-1)`, -0.881373587019543)
+		test(`Math.asinh(1)`, 0.881373587019543)
+		test(`Math.asinh(-0)`, -0)
+		test(`Math.asinh(0)`, 0)
+		test(`Math.asinh(-Infinity)`, -infinity)
+		test(`Math.asinh(Infinity)`, infinity)
+		test(`Math.asinh(2)`, 1.4436354751788103)
+	})
+}
+
 func TestMath_atan(t *testing.T) {
 	tt(t, func() {
 		test, _ := test()
@@ -119,6 +147,35 @@ func TestMath_atan2(t *testing.T) {
 	})
 }
 
+func TestMath_atanh(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.atanh(-2)`, naN)
+		test(`Math.atanh(2)`, naN)
+		test(`Math.atanh(-1)`, -infinity)
+		test(`Math.atanh(1)`, infinity)
+		test(`Math.atanh(0)`, 0)
+		test(`Math.atanh(0.5)`, 0.5493061443340548)
+	})
+}
+
+func TestMath_cbrt(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.cbrt(NaN)`, naN)
+		test(`Math.cbrt(-1)`, -1)
+		test(`Math.cbrt(1)`, 1)
+		test(`Math.cbrt(-0)`, -0)
+		test(`Math.cbrt(0)`, 0)
+		test(`Math.cbrt(-Infinity)`, -infinity)
+		test(`Math.cbrt(Infinity)`, infinity)
+		test(`Math.cbrt(null)`, 0)
+		test(`Math.cbrt(2)`, 1.2599210498948732)
+	})
+}
+
 func TestMath_ceil(t *testing.T) {
 	tt(t, func() {
 		test, _ := test()
@@ -150,6 +207,16 @@ func TestMath_cos(t *testing.T) {
 	})
 }
 
+func TestMath_cosh(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.cosh(0)`, 1)
+		test(`Math.cosh(1)`, 1.5430806348152437)
+		test(`Math.cosh(-1)`, 1.5430806348152437)
+	})
+}
+
 func TestMath_exp(t *testing.T) {
 	tt(t, func() {
 		test, _ := test()
@@ -162,6 +229,18 @@ func TestMath_exp(t *testing.T) {
 	})
 }
 
+func TestMath_expm1(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.expm1(0)`, 0)
+		test(`Math.expm1(1)`, 1.718281828459045)
+		test(`Math.expm1(-1)`, -0.6321205588285577)
+		test(`Math.expm1(2)`, 6.38905609893065)
+		test(`Math.expm1("foo")`, naN)
+	})
+}
+
 func TestMath_floor(t *testing.T) {
 	tt(t, func() {
 		test, _ := test()
@@ -193,6 +272,48 @@ func TestMath_log(t *testing.T) {
 	})
 }
 
+func TestMath_log10(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.log10(100000)`, 5)
+		test(`Math.log10(-2)`, naN)
+		test(`Math.log10(2)`, 0.3010299956639812)
+		test(`Math.log10(1)`, 0)
+		test(`Math.log10(-0)`, -infinity)
+		test(`Math.log10(0)`, -infinity)
+		test(`Math.log10(Infinity)`, infinity)
+	})
+}
+
+func TestMath_log1p(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.log1p(-2)`, naN)
+		test(`Math.log1p(-1)`, -infinity)
+		test(`Math.log1p(1)`, 0.6931471805599453)
+		test(`Math.log1p(-0)`, -0)
+		test(`Math.log1p(0)`, 0)
+		test(`Math.log1p(Infinity)`, infinity)
+	})
+}
+
+func TestMath_log2(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.log2(-2)`, naN)
+		test(`Math.log2(-0)`, -infinity)
+		test(`Math.log2(0)`, -infinity)
+		test(`Math.log2(1)`, 0)
+		test(`Math.log2(2)`, 1)
+		test(`Math.log2(5)`, 2.321928094887362)
+		test(`Math.log2(1024)`, 10)
+		test(`Math.log2(Infinity)`, infinity)
+	})
+}
+
 func TestMath_max(t *testing.T) {
 	tt(t, func() {
 		test, _ := test()
@@ -276,6 +397,20 @@ func TestMath_sin(t *testing.T) {
 	})
 }
 
+func TestMath_sinh(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.sinh(-Infinity)`, -infinity)
+		test(`Math.sinh(Infinity)`, infinity)
+		test(`Math.sinh(-0)`, -0)
+		test(`Math.sinh(0)`, 0)
+		test(`Math.sinh(-1)`, -1.1752011936438014)
+		test(`Math.sinh(1)`, 1.1752011936438014)
+		test(`Math.sinh(2)`, 3.626860407847019)
+	})
+}
+
 func TestMath_sqrt(t *testing.T) {
 	tt(t, func() {
 		test, _ := test()
@@ -303,3 +438,32 @@ func TestMath_tan(t *testing.T) {
 		test(`Math.tan(0.5)`, 0.5463024898437905)
 	})
 }
+
+func TestMath_tanh(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.tanh(Infinity)`, 1)
+		test(`Math.tanh(-Infinity)`, -1)
+		test(`Math.tanh(-1)`, -0.7615941559557649)
+		test(`Math.tanh(1)`, 0.7615941559557649)
+		test(`Math.tanh(-0)`, -0)
+		test(`Math.tanh(0)`, 0)
+	})
+}
+
+func TestMath_trunc(t *testing.T) {
+	tt(t, func() {
+		test, _ := test()
+
+		test(`Math.trunc(-Infinity)`, -infinity)
+		test(`Math.trunc(Infinity)`, infinity)
+		test(`Math.trunc(-0.123)`, -0)
+		test(`Math.trunc(0.123)`, 0)
+		test(`Math.trunc(-0)`, -0)
+		test(`Math.trunc(0)`, 0)
+		test(`Math.trunc("-1.123")`, -1)
+		test(`Math.trunc(13.37)`, 13)
+		test(`Math.trunc(42.84)`, 42)
+	})
+}