diff --git a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift
index 716151034..67a51aa2e 100644
--- a/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift
+++ b/IntegrationTests/TestSuites/Sources/PrimaryTests/main.swift
@@ -81,6 +81,22 @@ try test("Value Construction") {
     let prop_7 = getJSValue(this: globalObject1Ref, name: "prop_7")
     try expectEqual(Double.construct(from: prop_7), 3.14)
     try expectEqual(Float.construct(from: prop_7), 3.14)
+
+    for source: JSValue in [
+        .number(.infinity), .number(.nan),
+        .number(Double(UInt64.max).nextUp), .number(Double(Int64.min).nextDown)
+    ] {
+        try expectNil(Int.construct(from: source))
+        try expectNil(Int8.construct(from: source))
+        try expectNil(Int16.construct(from: source))
+        try expectNil(Int32.construct(from: source))
+        try expectNil(Int64.construct(from: source))
+        try expectNil(UInt.construct(from: source))
+        try expectNil(UInt8.construct(from: source))
+        try expectNil(UInt16.construct(from: source))
+        try expectNil(UInt32.construct(from: source))
+        try expectNil(UInt64.construct(from: source))
+    }
 }
 
 try test("Array Iterator") {
@@ -244,10 +260,11 @@ try test("Closure Lifetime") {
 #if JAVASCRIPTKIT_WITHOUT_WEAKREFS
     // Check diagnostics of use-after-free
     do {
+        let c1Line = #line + 1
         let c1 = JSClosure { $0[0] }
         c1.release()
         let error = try expectThrow(try evalClosure.throws(c1, JSValue.number(42.0))) as! JSValue
-        try expect("Error message should contains definition location", error.description.hasSuffix("PrimaryTests/main.swift:247"))
+        try expect("Error message should contains definition location", error.description.hasSuffix("PrimaryTests/main.swift:\(c1Line)"))
     }
 #endif
 
diff --git a/Sources/JavaScriptKit/ConstructibleFromJSValue.swift b/Sources/JavaScriptKit/ConstructibleFromJSValue.swift
index 1f43658f0..ce1e1c25f 100644
--- a/Sources/JavaScriptKit/ConstructibleFromJSValue.swift
+++ b/Sources/JavaScriptKit/ConstructibleFromJSValue.swift
@@ -35,15 +35,41 @@ extension Double: ConstructibleFromJSValue {}
 extension Float: ConstructibleFromJSValue {}
 
 extension SignedInteger where Self: ConstructibleFromJSValue {
+    /// Construct an instance of `SignedInteger` from the given `JSBigIntExtended`.
+    ///
+    /// If the value is too large to fit in the `Self` type, `nil` is returned.
+    ///
+    /// - Parameter bigInt: The `JSBigIntExtended` to decode
+    public init?(exactly bigInt: JSBigIntExtended) {
+        self.init(exactly: bigInt.int64Value)
+    }
+
+    /// Construct an instance of `SignedInteger` from the given `JSBigIntExtended`.
+    ///
+    /// Crash if the value is too large to fit in the `Self` type.
+    ///
+    /// - Parameter bigInt: The `JSBigIntExtended` to decode
     public init(_ bigInt: JSBigIntExtended) {
         self.init(bigInt.int64Value)
     }
+
+    /// Construct an instance of `SignedInteger` from the given `JSValue`.
+    ///
+    /// Returns `nil` if one of the following conditions is met:
+    /// - The value is not a number or a bigint.
+    /// - The value is a number that does not fit or cannot be represented
+    ///   in the `Self` type (e.g. NaN, Infinity).
+    /// - The value is a bigint that does not fit in the `Self` type.
+    ///
+    /// If the value is a number, it is rounded towards zero before conversion.
+    ///
+    /// - Parameter value: The `JSValue` to decode
     public static func construct(from value: JSValue) -> Self? {
         if let number = value.number {
-            return Self(number)
+            return Self(exactly: number.rounded(.towardZero))
         }
         if let bigInt = value.bigInt as? JSBigIntExtended {
-            return Self(bigInt)
+            return Self(exactly: bigInt)
         }
         return nil
     }
@@ -55,15 +81,41 @@ extension Int32: ConstructibleFromJSValue {}
 extension Int64: ConstructibleFromJSValue {}
 
 extension UnsignedInteger where Self: ConstructibleFromJSValue {
+
+    /// Construct an instance of `UnsignedInteger` from the given `JSBigIntExtended`.
+    ///
+    /// Returns `nil` if the value is negative or too large to fit in the `Self` type.
+    ///
+    /// - Parameter bigInt: The `JSBigIntExtended` to decode
+    public init?(exactly bigInt: JSBigIntExtended) {
+        self.init(exactly: bigInt.uInt64Value)
+    }
+
+    /// Construct an instance of `UnsignedInteger` from the given `JSBigIntExtended`.
+    ///
+    /// Crash if the value is negative or too large to fit in the `Self` type.
+    ///
+    /// - Parameter bigInt: The `JSBigIntExtended` to decode
     public init(_ bigInt: JSBigIntExtended) {
         self.init(bigInt.uInt64Value)
     }
+
+    /// Construct an instance of `UnsignedInteger` from the given `JSValue`.
+    ///
+    /// Returns `nil` if one of the following conditions is met:
+    /// - The value is not a number or a bigint.
+    /// - The value is a number that does not fit or cannot be represented
+    ///  in the `Self` type (e.g. NaN, Infinity).
+    /// - The value is a bigint that does not fit in the `Self` type.
+    /// - The value is negative.
+    ///
+    /// - Parameter value: The `JSValue` to decode
     public static func construct(from value: JSValue) -> Self? {
         if let number = value.number {
-            return Self(number)
+            return Self(exactly: number.rounded(.towardZero))
         }
         if let bigInt = value.bigInt as? JSBigIntExtended {
-            return Self(bigInt)
+            return Self(exactly: bigInt)
         }
         return nil
     }