Skip to content

Commit 47b62d1

Browse files
tsaichienmeta-codesync[bot]
authored andcommitted
Add Error creation APIs for all standard JS error types (facebook#56159)
Summary: Pull Request resolved: facebook#56159 Add Error creation APIs to JSI to allow native code to create JavaScript Error objects of all standard types. Users can also call the static methods in `JSError` that creates a `JSError` instance that holds the intended error type. Changelog: [Internal] Reviewed By: lavenzg Differential Revision: D95854323
1 parent 8f0f4f7 commit 47b62d1

File tree

3 files changed

+207
-0
lines changed

3 files changed

+207
-0
lines changed

packages/react-native/ReactCommon/jsi/jsi/jsi.cpp

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,6 +574,34 @@ Uint8Array Runtime::createUint8Array(
574574
return Uint8Array(cloneObject(getPointerValue(result.getObject(*this))));
575575
}
576576

577+
Value Runtime::createError(const String& msg) {
578+
return callGlobalFunction(*this, "Error", Value(*this, msg));
579+
}
580+
581+
Value Runtime::createEvalError(const String& msg) {
582+
return callGlobalFunction(*this, "EvalError", Value(*this, msg));
583+
}
584+
585+
Value Runtime::createRangeError(const String& msg) {
586+
return callGlobalFunction(*this, "RangeError", Value(*this, msg));
587+
}
588+
589+
Value Runtime::createReferenceError(const String& msg) {
590+
return callGlobalFunction(*this, "ReferenceError", Value(*this, msg));
591+
}
592+
593+
Value Runtime::createSyntaxError(const String& msg) {
594+
return callGlobalFunction(*this, "SyntaxError", Value(*this, msg));
595+
}
596+
597+
Value Runtime::createTypeError(const String& msg) {
598+
return callGlobalFunction(*this, "TypeError", Value(*this, msg));
599+
}
600+
601+
Value Runtime::createURIError(const String& msg) {
602+
return callGlobalFunction(*this, "URIError", Value(*this, msg));
603+
}
604+
577605
bool Runtime::detached(const ArrayBuffer& buffer) {
578606
Value prop = buffer.getProperty(*this, "detached");
579607
if (!prop.isBool()) {
@@ -967,6 +995,40 @@ JSError::JSError(Value&& value, std::string message, std::string stack)
967995
message_(std::move(message)),
968996
stack_(std::move(stack)) {}
969997

998+
JSError JSError::createEvalError(IRuntime& rt, const std::string& message) {
999+
return JSError(
1000+
message, rt, rt.createEvalError(String::createFromUtf8(rt, message)));
1001+
}
1002+
1003+
JSError JSError::createRangeError(IRuntime& rt, const std::string& message) {
1004+
return JSError(
1005+
message, rt, rt.createRangeError(String::createFromUtf8(rt, message)));
1006+
}
1007+
1008+
JSError JSError::createReferenceError(
1009+
IRuntime& rt,
1010+
const std::string& message) {
1011+
return JSError(
1012+
message,
1013+
rt,
1014+
rt.createReferenceError(String::createFromUtf8(rt, message)));
1015+
}
1016+
1017+
JSError JSError::createSyntaxError(IRuntime& rt, const std::string& message) {
1018+
return JSError(
1019+
message, rt, rt.createSyntaxError(String::createFromUtf8(rt, message)));
1020+
}
1021+
1022+
JSError JSError::createTypeError(IRuntime& rt, const std::string& message) {
1023+
return JSError(
1024+
message, rt, rt.createTypeError(String::createFromUtf8(rt, message)));
1025+
}
1026+
1027+
JSError JSError::createURIError(IRuntime& rt, const std::string& message) {
1028+
return JSError(
1029+
message, rt, rt.createURIError(String::createFromUtf8(rt, message)));
1030+
}
1031+
9701032
void JSError::setValue(IRuntime& rt, Value&& value) {
9711033
value_ = std::make_shared<Value>(std::move(value));
9721034

packages/react-native/ReactCommon/jsi/jsi/jsi.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -657,6 +657,24 @@ class JSI_EXPORT IRuntime : public ICast {
657657
virtual Uint8Array
658658
createUint8Array(const ArrayBuffer& buffer, size_t offset, size_t length) = 0;
659659

660+
/// Create a new Error object with the message property set to \p message.
661+
virtual Value createError(const String& msg) = 0;
662+
/// Create a new EvalError object with the message property set to \p message.
663+
virtual Value createEvalError(const String& msg) = 0;
664+
/// Create a new RangeError object with the message property set to \p
665+
/// message.
666+
virtual Value createRangeError(const String& msg) = 0;
667+
/// Create a new ReferenceError object with the message property set to \p
668+
/// message.
669+
virtual Value createReferenceError(const String& msg) = 0;
670+
/// Create a new SyntaxError object with the message property set to \p
671+
/// message.
672+
virtual Value createSyntaxError(const String& msg) = 0;
673+
/// Create a new TypeError object with the message property set to \p message.
674+
virtual Value createTypeError(const String& msg) = 0;
675+
/// Create a new URIError object with the message property set to \p message.
676+
virtual Value createURIError(const String& msg) = 0;
677+
660678
protected:
661679
virtual ~IRuntime() = default;
662680
};
@@ -760,6 +778,14 @@ class JSI_EXPORT Runtime : public IRuntime {
760778
size_t offset,
761779
size_t length) override;
762780

781+
Value createError(const String& msg) override;
782+
Value createEvalError(const String& msg) override;
783+
Value createRangeError(const String& msg) override;
784+
Value createReferenceError(const String& msg) override;
785+
Value createSyntaxError(const String& msg) override;
786+
Value createTypeError(const String& msg) override;
787+
Value createURIError(const String& msg) override;
788+
763789
protected:
764790
friend class Pointer;
765791
friend class PropNameID;
@@ -2120,6 +2146,30 @@ class JSI_EXPORT JSError : public JSIException {
21202146
/// in recursively invoking the JSError constructor.
21212147
JSError(Value&& value, std::string message, std::string stack);
21222148

2149+
/// Creates a JSError referring to new \c EvalError instance. The error
2150+
/// message property is set to given \c message.
2151+
static JSError createEvalError(IRuntime& rt, const std::string& message);
2152+
2153+
/// Creates a JSError referring to new \c RangeError instance. The error
2154+
/// message property is set to given \c message.
2155+
static JSError createRangeError(IRuntime& rt, const std::string& message);
2156+
2157+
/// Creates a JSError referring to new \c ReferenceError instance. The error
2158+
/// message property is set to given \c message.
2159+
static JSError createReferenceError(IRuntime& rt, const std::string& message);
2160+
2161+
/// Creates a JSError referring to new \c SyntaxError instance. The error
2162+
/// message property is set to given \c message.
2163+
static JSError createSyntaxError(IRuntime& rt, const std::string& message);
2164+
2165+
/// Creates a JSError referring to new \c TypeError instance. The error
2166+
/// message property is set to given \c message.
2167+
static JSError createTypeError(IRuntime& rt, const std::string& message);
2168+
2169+
/// Creates a JSError referring to new \c URIError instance. The error
2170+
/// message property is set to given \c message.
2171+
static JSError createURIError(IRuntime& rt, const std::string& message);
2172+
21232173
JSError(const JSError&) = default;
21242174

21252175
virtual ~JSError();

packages/react-native/ReactCommon/jsi/jsi/test/testlib.cpp

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1428,6 +1428,101 @@ TEST_P(JSITest, JSErrorTest) {
14281428
JSIException);
14291429
}
14301430

1431+
TEST_P(JSITest, CreateErrorTest) {
1432+
// Test JSError::createEvalError
1433+
{
1434+
try {
1435+
throw JSError::createEvalError(rt, "eval error");
1436+
} catch (const JSError& e) {
1437+
// getMessage() checks the C++ JSError's cached message.
1438+
// The "message" property check verifies the JS object was constructed
1439+
// correctly, since they are populated independently.
1440+
EXPECT_EQ(e.getMessage(), "eval error");
1441+
Object caughtObj = e.value().getObject(rt);
1442+
EXPECT_EQ(
1443+
caughtObj.getProperty(rt, "message").getString(rt).utf8(rt),
1444+
"eval error");
1445+
EXPECT_TRUE(rt.instanceOf(
1446+
caughtObj, rt.global().getPropertyAsFunction(rt, "EvalError")));
1447+
}
1448+
}
1449+
1450+
// Test JSError::createRangeError
1451+
{
1452+
try {
1453+
throw JSError::createRangeError(rt, "range error");
1454+
} catch (const JSError& e) {
1455+
EXPECT_EQ(e.getMessage(), "range error");
1456+
Object caughtObj = e.value().getObject(rt);
1457+
EXPECT_EQ(
1458+
caughtObj.getProperty(rt, "message").getString(rt).utf8(rt),
1459+
"range error");
1460+
EXPECT_TRUE(rt.instanceOf(
1461+
caughtObj, rt.global().getPropertyAsFunction(rt, "RangeError")));
1462+
}
1463+
}
1464+
1465+
// Test JSError::createReferenceError
1466+
{
1467+
try {
1468+
throw JSError::createReferenceError(rt, "reference error");
1469+
} catch (const JSError& e) {
1470+
EXPECT_EQ(e.getMessage(), "reference error");
1471+
Object caughtObj = e.value().getObject(rt);
1472+
EXPECT_EQ(
1473+
caughtObj.getProperty(rt, "message").getString(rt).utf8(rt),
1474+
"reference error");
1475+
EXPECT_TRUE(rt.instanceOf(
1476+
caughtObj, rt.global().getPropertyAsFunction(rt, "ReferenceError")));
1477+
}
1478+
}
1479+
1480+
// Test JSError::createSyntaxError
1481+
{
1482+
try {
1483+
throw JSError::createSyntaxError(rt, "syntax error");
1484+
} catch (const JSError& e) {
1485+
EXPECT_EQ(e.getMessage(), "syntax error");
1486+
Object caughtObj = e.value().getObject(rt);
1487+
EXPECT_EQ(
1488+
caughtObj.getProperty(rt, "message").getString(rt).utf8(rt),
1489+
"syntax error");
1490+
EXPECT_TRUE(rt.instanceOf(
1491+
caughtObj, rt.global().getPropertyAsFunction(rt, "SyntaxError")));
1492+
}
1493+
}
1494+
1495+
// Test JSError::createTypeError
1496+
{
1497+
try {
1498+
throw JSError::createTypeError(rt, "type error");
1499+
} catch (const JSError& e) {
1500+
EXPECT_EQ(e.getMessage(), "type error");
1501+
Object caughtObj = e.value().getObject(rt);
1502+
EXPECT_EQ(
1503+
caughtObj.getProperty(rt, "message").getString(rt).utf8(rt),
1504+
"type error");
1505+
EXPECT_TRUE(rt.instanceOf(
1506+
caughtObj, rt.global().getPropertyAsFunction(rt, "TypeError")));
1507+
}
1508+
}
1509+
1510+
// Test JSError::createURIError
1511+
{
1512+
try {
1513+
throw JSError::createURIError(rt, "uri error");
1514+
} catch (const JSError& e) {
1515+
EXPECT_EQ(e.getMessage(), "uri error");
1516+
Object caughtObj = e.value().getObject(rt);
1517+
EXPECT_EQ(
1518+
caughtObj.getProperty(rt, "message").getString(rt).utf8(rt),
1519+
"uri error");
1520+
EXPECT_TRUE(rt.instanceOf(
1521+
caughtObj, rt.global().getPropertyAsFunction(rt, "URIError")));
1522+
}
1523+
}
1524+
}
1525+
14311526
TEST_P(JSITest, MicrotasksTest) {
14321527
try {
14331528
rt.global().setProperty(rt, "globalValue", String::createFromAscii(rt, ""));

0 commit comments

Comments
 (0)