22
33#include < sstream>
44#include < string>
5+ #include < vector>
56
67#include " ffi/NativeScriptException.h"
78#include " js_native_api.h"
@@ -34,6 +35,64 @@ extern "C" void NSLog(CFStringRef format, ...);
3435
3536namespace nativescript {
3637
38+ namespace {
39+
40+ bool readStringValue (napi_env env, napi_value value, std::string& result) {
41+ if (value == nullptr ) {
42+ return false ;
43+ }
44+
45+ size_t length = 0 ;
46+ if (napi_get_value_string_utf8 (env, value, nullptr , 0 , &length) != napi_ok) {
47+ return false ;
48+ }
49+
50+ std::vector<char > buffer (length + 1 );
51+ size_t copied = 0 ;
52+ if (napi_get_value_string_utf8 (env, value, buffer.data (), buffer.size (),
53+ &copied) != napi_ok) {
54+ return false ;
55+ }
56+
57+ result.assign (buffer.data (), copied);
58+ return true ;
59+ }
60+
61+ bool throwPendingException (napi_env env, const std::string& message) {
62+ bool isPending = false ;
63+ if (napi_is_exception_pending (env, &isPending) != napi_ok || !isPending) {
64+ return false ;
65+ }
66+
67+ napi_value exception = nullptr ;
68+ napi_get_and_clear_last_exception (env, &exception);
69+
70+ if (exception != nullptr &&
71+ napi_util::is_of_type (env, exception, napi_object)) {
72+ throw NativeScriptException (env, exception, message);
73+ }
74+
75+ throw NativeScriptException (env, message);
76+ }
77+
78+ bool coerceToString (napi_env env, napi_value value, std::string& result) {
79+ napi_value stringValue = nullptr ;
80+ if (napi_coerce_to_string (env, value, &stringValue) != napi_ok ||
81+ stringValue == nullptr ) {
82+ throwPendingException (env, " Error converting console argument to string" );
83+ return false ;
84+ }
85+
86+ if (!readStringValue (env, stringValue, result)) {
87+ throwPendingException (env, " Error reading console argument string" );
88+ return false ;
89+ }
90+
91+ return true ;
92+ }
93+
94+ } // namespace
95+
3796JS_CLASS_INIT (Console::Init) {
3897 napi_value Console, console;
3998
@@ -65,17 +124,38 @@ JS_METHOD(Console::Constructor) {
65124}
66125
67126std::string transformJSObject (napi_env env, napi_value object) {
68- napi_value toStringFunc;
127+ napi_value toStringFunc = nullptr ;
69128 bool hasToString = false ;
70129
71130 // Check if the object has a toString method
72- napi_has_named_property (env, object, " toString" , &hasToString);
131+ if (napi_has_named_property (env, object, " toString" , &hasToString) !=
132+ napi_ok) {
133+ throwPendingException (env, " Error reading console object toString" );
134+ return " [object Object]" ;
135+ }
136+
73137 if (hasToString) {
74- napi_get_named_property (env, object, " toString" , &toStringFunc);
75- if (napi_util::is_of_type (env, toStringFunc, napi_function)) {
76- napi_value result;
77- napi_call_function (env, object, toStringFunc, 0 , nullptr , &result);
78- auto value = napi_util::get_cxx_string (env, result);
138+ if (napi_get_named_property (env, object, " toString" , &toStringFunc) !=
139+ napi_ok) {
140+ throwPendingException (env, " Error reading console object toString" );
141+ return " [object Object]" ;
142+ }
143+
144+ if (toStringFunc != nullptr &&
145+ napi_util::is_of_type (env, toStringFunc, napi_function)) {
146+ napi_value result = nullptr ;
147+ if (napi_call_function (env, object, toStringFunc, 0 , nullptr , &result) !=
148+ napi_ok ||
149+ result == nullptr ) {
150+ throwPendingException (env, " Error converting console object to string" );
151+ return " [object Object]" ;
152+ }
153+
154+ std::string value;
155+ if (!coerceToString (env, result, value)) {
156+ return " [object Object]" ;
157+ }
158+
79159 auto hasCustomToStringImplementation =
80160 value.find (" [object Object]" ) == std::string::npos;
81161 if (hasCustomToStringImplementation) return value;
@@ -88,29 +168,48 @@ std::string transformJSObject(napi_env env, napi_value object) {
88168std::string buildStringFromArg (napi_env env, napi_value val,
89169 napi_value inspectSymbol) {
90170 napi_valuetype type;
91- napi_typeof (env, val, &type);
171+ if (napi_typeof (env, val, &type) != napi_ok) {
172+ throwPendingException (env, " Error reading console argument type" );
173+ return " <unknown>" ;
174+ }
92175
93176 if (type == napi_function) {
94- napi_value funcString;
95- napi_coerce_to_string (env, val, &funcString);
96- return napi_util::get_string_value (env, funcString);
177+ std::string funcString;
178+ if (coerceToString (env, val, funcString)) {
179+ return funcString;
180+ }
181+ return " <function>" ;
97182 } else if (napi_util::is_array (env, val)) {
98183 napi_value cachedSelf = val;
99184
100185 // Get array length
101- uint32_t arrayLength;
102- napi_get_array_length (env, val, &arrayLength);
186+ uint32_t arrayLength = 0 ;
187+ if (napi_get_array_length (env, val, &arrayLength) != napi_ok) {
188+ throwPendingException (env, " Error reading console array length" );
189+ return " []" ;
190+ }
103191
104192 std::stringstream arrayStr;
105193 arrayStr << " [" ;
106194
107195 for (uint32_t i = 0 ; i < arrayLength; i++) {
108- napi_value propertyValue;
109- napi_get_element (env, val, i, &propertyValue);
196+ napi_value propertyValue = nullptr ;
197+ if (napi_get_element (env, val, i, &propertyValue) != napi_ok ||
198+ propertyValue == nullptr ) {
199+ throwPendingException (env, " Error reading console array element" );
200+ arrayStr << " <unknown>" ;
201+ if (i != arrayLength - 1 ) {
202+ arrayStr << " , " ;
203+ }
204+ continue ;
205+ }
110206
111207 // Check for circular reference
112208 bool isStrictEqual = false ;
113- napi_strict_equals (env, propertyValue, cachedSelf, &isStrictEqual);
209+ if (napi_strict_equals (env, propertyValue, cachedSelf, &isStrictEqual) !=
210+ napi_ok) {
211+ throwPendingException (env, " Error comparing console array element" );
212+ }
114213
115214 if (isStrictEqual) {
116215 arrayStr << " [Circular]" ;
@@ -132,20 +231,32 @@ std::string buildStringFromArg(napi_env env, napi_value val,
132231 napi_status getInspectStatus =
133232 napi_get_property (env, val, inspectSymbol, &inspectFunc);
134233 if (getInspectStatus == napi_ok &&
234+ inspectFunc != nullptr &&
135235 napi_util::is_of_type (env, inspectFunc, napi_function)) {
136- napi_value inspectedValue;
137- napi_call_function (env, val, inspectFunc, 0 , nullptr , &inspectedValue);
236+ napi_value inspectedValue = nullptr ;
237+ if (napi_call_function (env, val, inspectFunc, 0 , nullptr ,
238+ &inspectedValue) != napi_ok ||
239+ inspectedValue == nullptr ) {
240+ throwPendingException (env, " Error inspecting console object" );
241+ return " [object Object]" ;
242+ }
138243 return buildStringFromArg (env, inspectedValue, inspectSymbol);
244+ } else if (getInspectStatus != napi_ok) {
245+ throwPendingException (env, " Error reading console inspect function" );
139246 }
140247 return transformJSObject (env, val);
141248 } else if (type == napi_symbol) {
142- napi_value symString;
143- napi_coerce_to_string (env, val, &symString);
144- return " Symbol(" + napi_util::get_cxx_string (env, symString) + " )" ;
249+ std::string symString;
250+ if (coerceToString (env, val, symString)) {
251+ return symString;
252+ }
253+ return " Symbol()" ;
145254 } else {
146- napi_value defaultToString;
147- napi_coerce_to_string (env, val, &defaultToString);
148- return napi_util::get_string_value (env, defaultToString);
255+ std::string defaultToString;
256+ if (coerceToString (env, val, defaultToString)) {
257+ return defaultToString;
258+ }
259+ return " <unknown>" ;
149260 }
150261}
151262
0 commit comments