diff --git a/bin/ch/ChakraRtInterface.cpp b/bin/ch/ChakraRtInterface.cpp
index e2f2940f9f9..5102cd487da 100644
--- a/bin/ch/ChakraRtInterface.cpp
+++ b/bin/ch/ChakraRtInterface.cpp
@@ -144,6 +144,7 @@ bool ChakraRTInterface::LoadChakraDll(ArgInfo* argInfo, HINSTANCE *outLibrary)
m_jsApiHooks.pfJsrtParse = (JsAPIHooks::JsrtParse)GetChakraCoreSymbol(library, "JsParse");
m_jsApiHooks.pfJsrtSerialize = (JsAPIHooks::JsrtSerialize)GetChakraCoreSymbol(library, "JsSerialize");
m_jsApiHooks.pfJsrtRunSerialized = (JsAPIHooks::JsrtRunSerialized)GetChakraCoreSymbol(library, "JsRunSerialized");
+ m_jsApiHooks.pfJsrtGetStringLength = (JsAPIHooks::JsrtGetStringLength)GetChakraCoreSymbol(library, "JsGetStringLength");
m_jsApiHooks.pfJsrtCreateString = (JsAPIHooks::JsrtCreateString)GetChakraCoreSymbol(library, "JsCreateString");
m_jsApiHooks.pfJsrtCreateStringUtf16 = (JsAPIHooks::JsrtCreateStringUtf16)GetChakraCoreSymbol(library, "JsCreateStringUtf16");
m_jsApiHooks.pfJsrtCopyString = (JsAPIHooks::JsrtCopyString)GetChakraCoreSymbol(library, "JsCopyString");
diff --git a/bin/ch/ChakraRtInterface.h b/bin/ch/ChakraRtInterface.h
index 9eb39e4df16..cde09412bed 100644
--- a/bin/ch/ChakraRtInterface.h
+++ b/bin/ch/ChakraRtInterface.h
@@ -77,7 +77,8 @@ struct JsAPIHooks
typedef JsErrorCode(WINAPI *JsrtParse)(JsValueRef script, JsSourceContext sourceContext, JsValueRef sourceUrl, JsParseScriptAttributes parseAttributes, JsValueRef *result);
typedef JsErrorCode(WINAPI *JsrtSerialize)(JsValueRef script, JsValueRef *buffer, JsParseScriptAttributes parseAttributes);
typedef JsErrorCode(WINAPI *JsrtRunSerialized)(JsValueRef buffer, JsSerializedLoadScriptCallback scriptLoadCallback, JsSourceContext sourceContext, JsValueRef sourceUrl, JsValueRef * result);
- typedef JsErrorCode(WINAPI *JsrtCopyString)(JsValueRef value, char* buffer, size_t bufferSize, size_t* written);
+ typedef JsErrorCode(WINAPI *JsrtGetStringLength)(JsValueRef value, int *stringLength);
+ typedef JsErrorCode(WINAPI *JsrtCopyString)(JsValueRef value, char* buffer, size_t bufferSize, size_t* writtenLength, size_t* actualLength);
typedef JsErrorCode(WINAPI *JsrtCreateString)(const char *content, size_t length, JsValueRef *value);
typedef JsErrorCode(WINAPI *JsrtCreateStringUtf16)(const uint16_t *content, size_t length, JsValueRef *value);
@@ -172,6 +173,7 @@ struct JsAPIHooks
JsrtParse pfJsrtParse;
JsrtSerialize pfJsrtSerialize;
JsrtRunSerialized pfJsrtRunSerialized;
+ JsrtGetStringLength pfJsrtGetStringLength;
JsrtCreateString pfJsrtCreateString;
JsrtCreateStringUtf16 pfJsrtCreateStringUtf16;
JsrtCopyString pfJsrtCopyString;
@@ -396,7 +398,8 @@ class ChakraRTInterface
static JsErrorCode WINAPI JsParse(JsValueRef script, JsSourceContext sourceContext, JsValueRef sourceUrl, JsParseScriptAttributes parseAttributes, JsValueRef *result) { return HOOK_JS_API(Parse(script, sourceContext, sourceUrl, parseAttributes, result)); }
static JsErrorCode WINAPI JsSerialize(JsValueRef script, JsValueRef *buffer, JsParseScriptAttributes parseAttributes) { return HOOK_JS_API(Serialize(script, buffer, parseAttributes)); }
static JsErrorCode WINAPI JsRunSerialized(JsValueRef buffer, JsSerializedLoadScriptCallback scriptLoadCallback, JsSourceContext sourceContext, JsValueRef sourceUrl, JsValueRef * result) { return HOOK_JS_API(RunSerialized(buffer, scriptLoadCallback, sourceContext, sourceUrl, result)); }
- static JsErrorCode WINAPI JsCopyString(JsValueRef value, char* buffer, size_t bufferSize, size_t* written) { return HOOK_JS_API(CopyString(value, buffer, bufferSize, written)); }
+ static JsErrorCode WINAPI JsGetStringLength(JsValueRef value, int *stringLength) { return HOOK_JS_API(GetStringLength(value, stringLength)); }
+ static JsErrorCode WINAPI JsCopyString(JsValueRef value, char* buffer, size_t bufferSize, size_t* writtenLength, size_t* actualLength) { return HOOK_JS_API(CopyString(value, buffer, bufferSize, writtenLength, actualLength)); }
static JsErrorCode WINAPI JsCreateString(const char *content, size_t length, JsValueRef *value) { return HOOK_JS_API(CreateString(content, length, value)); }
static JsErrorCode WINAPI JsCreateStringUtf16(const uint16_t *content, size_t length, JsValueRef *value) { return HOOK_JS_API(CreateStringUtf16(content, length, value)); }
static JsErrorCode WINAPI JsCreatePropertyId(const char *name, size_t length, JsPropertyIdRef *propertyId) { return HOOK_JS_API(CreatePropertyId(name, length, propertyId)); }
diff --git a/bin/ch/stdafx.h b/bin/ch/stdafx.h
index 2dbcb55d411..4613f05110b 100644
--- a/bin/ch/stdafx.h
+++ b/bin/ch/stdafx.h
@@ -206,18 +206,39 @@ class AutoString
{
strValue = value;
}
+ int strLen = 0;
+ size_t writtenLen = 0;
+ size_t actualLen = 0;
if (errorCode == JsNoError)
{
- size_t len = 0;
- errorCode = ChakraRTInterface::JsCopyString(strValue, nullptr, 0, &len);
+ errorCode = ChakraRTInterface::JsGetStringLength(strValue, &strLen);
if (errorCode == JsNoError)
{
- data = (char*) malloc((len + 1) * sizeof(char));
- ChakraRTInterface::JsCopyString(strValue, data, len + 1, &length);
- AssertMsg(len == length, "If you see this message.. There is something seriously wrong. Good Luck!");
- *(data + len) = char(0);
+ // Assume ascii characters
+ data = (char*)malloc((strLen + 1) * sizeof(char));
+ errorCode = ChakraRTInterface::JsCopyString(strValue, data, strLen, &writtenLen, &actualLen);
+ if (errorCode == JsNoError)
+ {
+ // If non-ascii, take slow path
+ if (writtenLen != actualLen)
+ {
+ free(data);
+ data = (char*)malloc((actualLen + 1) * sizeof(char));
+
+ errorCode = ChakraRTInterface::JsCopyString(strValue, data, actualLen + 1, &writtenLen, nullptr);
+ if (errorCode == JsNoError)
+ {
+ AssertMsg(actualLen == writtenLen, "If you see this message.. There is something seriously wrong. Good Luck!");
+
+ }
+ }
+ }
}
}
+ if (errorCode == JsNoError)
+ {
+ *(data + actualLen) = char(0);
+ }
return errorCode;
}
diff --git a/lib/Jsrt/ChakraCore.h b/lib/Jsrt/ChakraCore.h
index 3ebefafd641..47eec84bfb9 100644
--- a/lib/Jsrt/ChakraCore.h
+++ b/lib/Jsrt/ChakraCore.h
@@ -286,13 +286,23 @@ CHAKRA_API
///
/// When size of the `buffer` is unknown,
/// `buffer` argument can be nullptr.
-/// In that case, `written` argument will return the length needed.
+/// In that case, `actualLength` argument will return the length needed to
+/// accomodate all the UTF8 decoded bytes present in `value`.
+/// `writtenLength` will only get populated when valid `buffer` is passed as
+/// argument.
///
///
/// JavascriptString value
/// Pointer to buffer
/// Buffer size
-/// Total number of characters written
+/// Total number of UTF8 decoded bytes written. This is only
+/// populated when passed with non-null `buffer`,else is
+/// set to 0.
+///
+/// Total number of UTF8 decoded bytes present in `value`.
+/// Useful to initialize buffer of appropriate size that
+/// can be passed in to this API.
+///
///
/// The code JsNoError if the operation succeeded, a failure code otherwise.
///
@@ -301,7 +311,8 @@ CHAKRA_API
_In_ JsValueRef value,
_Out_opt_ char* buffer,
_In_ size_t bufferSize,
- _Out_opt_ size_t* written);
+ _Out_opt_ size_t* writtenLength,
+ _Out_opt_ size_t* actualLength);
///
/// Write string value into Utf16 string buffer
diff --git a/lib/Jsrt/Jsrt.cpp b/lib/Jsrt/Jsrt.cpp
index eb705a0f472..05f2fe77f41 100644
--- a/lib/Jsrt/Jsrt.cpp
+++ b/lib/Jsrt/Jsrt.cpp
@@ -4252,7 +4252,8 @@ CHAKRA_API JsCopyString(
_In_ JsValueRef value,
_Out_opt_ char* buffer,
_In_ size_t bufferSize,
- _Out_opt_ size_t* length)
+ _Out_opt_ size_t* writtenLength,
+ _Out_opt_ size_t* actualLength)
{
PARAM_NOT_NULL(value);
VALIDATE_JSREF(value);
@@ -4266,14 +4267,12 @@ CHAKRA_API JsCopyString(
}
utf8::WideToNarrow utf8Str(str, strLength);
- if (!buffer)
+ if (actualLength)
{
- if (length)
- {
- *length = utf8Str.Length();
- }
+ *actualLength = utf8Str.Length();
}
- else
+
+ if (buffer)
{
size_t count = min(bufferSize, utf8Str.Length());
// Try to copy whole characters if buffer size insufficient
@@ -4284,11 +4283,15 @@ CHAKRA_API JsCopyString(
(LPCUTF8)(const char*)utf8Str, utf8Str.Length(), maxFitChars);
memmove(buffer, utf8Str, sizeof(char) * count);
- if (length)
+ if (writtenLength)
{
- *length = count;
+ *writtenLength = count;
}
}
+ else if (writtenLength)
+ {
+ *writtenLength = 0;
+ }
return JsNoError;
}
diff --git a/test/native-tests/test-c98/sample.cpp b/test/native-tests/test-c98/sample.cpp
index b0c60996efb..34ff587edf7 100644
--- a/test/native-tests/test-c98/sample.cpp
+++ b/test/native-tests/test-c98/sample.cpp
@@ -63,9 +63,9 @@ int main()
// Project script result back to C++.
char *resultSTR = nullptr;
size_t stringLength;
- FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, &stringLength));
+ FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, nullptr, &stringLength));
resultSTR = (char*)malloc(stringLength + 1);
- FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr));
+ FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr, nullptr));
resultSTR[stringLength] = 0;
printf("Result -> %s \n", resultSTR);
diff --git a/test/native-tests/test-char/sample.cpp b/test/native-tests/test-char/sample.cpp
index d85ce9300b3..ea86ee1113b 100644
--- a/test/native-tests/test-char/sample.cpp
+++ b/test/native-tests/test-char/sample.cpp
@@ -73,9 +73,9 @@ int main()
// Project script result back to C++.
char *resultSTR = nullptr;
size_t stringLength;
- FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, &stringLength));
+ FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, nullptr, &stringLength));
resultSTR = (char*)malloc(stringLength + 1);
- FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr));
+ FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr, nullptr));
resultSTR[stringLength] = 0;
printf("Result -> %s \n", resultSTR);
diff --git a/test/native-tests/test-char16/sample.cpp b/test/native-tests/test-char16/sample.cpp
index 86cb78a4985..4e78b7677ec 100644
--- a/test/native-tests/test-char16/sample.cpp
+++ b/test/native-tests/test-char16/sample.cpp
@@ -69,9 +69,9 @@ int main()
// Project script result back to C++.
char *resultSTR = nullptr;
size_t stringLength;
- FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, &stringLength));
+ FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, nullptr, &stringLength));
resultSTR = (char*) malloc(stringLength + 1);
- FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr));
+ FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr, nullptr));
resultSTR[stringLength] = 0;
printf("Result -> %s \n", resultSTR);
diff --git a/test/native-tests/test-python/helloWorld.py b/test/native-tests/test-python/helloWorld.py
index 6283868d54f..10ccbcf3887 100755
--- a/test/native-tests/test-python/helloWorld.py
+++ b/test/native-tests/test-python/helloWorld.py
@@ -56,12 +56,12 @@
stringLength = c_size_t();
# Get buffer size needed for the result string
-chakraCore.JsCopyString(resultJSString, 0, 0, byref(stringLength));
+chakraCore.JsCopyString(resultJSString, 0, 0, 0, byref(stringLength));
resultSTR = create_string_buffer(stringLength.value + 1); # buffer is big enough to store the result
# Get String from JsValueRef
-chakraCore.JsCopyString(resultJSString, byref(resultSTR), stringLength.value + 1, 0);
+chakraCore.JsCopyString(resultJSString, byref(resultSTR), stringLength.value + 1, 0, 0);
# Set `null-ending` to the end
resultSTRLastByte = (c_char * stringLength.value).from_address(addressof(resultSTR))
diff --git a/test/native-tests/test-shared-basic/sample.cpp b/test/native-tests/test-shared-basic/sample.cpp
index 56d985bf8bc..3018cc9ea16 100644
--- a/test/native-tests/test-shared-basic/sample.cpp
+++ b/test/native-tests/test-shared-basic/sample.cpp
@@ -57,9 +57,9 @@ int main()
// Project script result back to C++.
char *resultSTR = nullptr;
size_t stringLength;
- FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, &stringLength));
+ FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, nullptr, &stringLength));
resultSTR = (char*) malloc(stringLength + 1);
- FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr));
+ FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr, nullptr));
resultSTR[stringLength] = 0;
printf("Result -> %s \n", resultSTR);
diff --git a/test/native-tests/test-static-native/sample.cpp b/test/native-tests/test-static-native/sample.cpp
index 56d985bf8bc..3018cc9ea16 100644
--- a/test/native-tests/test-static-native/sample.cpp
+++ b/test/native-tests/test-static-native/sample.cpp
@@ -57,9 +57,9 @@ int main()
// Project script result back to C++.
char *resultSTR = nullptr;
size_t stringLength;
- FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, &stringLength));
+ FAIL_CHECK(JsCopyString(resultJSString, nullptr, 0, nullptr, &stringLength));
resultSTR = (char*) malloc(stringLength + 1);
- FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr));
+ FAIL_CHECK(JsCopyString(resultJSString, resultSTR, stringLength + 1, nullptr, nullptr));
resultSTR[stringLength] = 0;
printf("Result -> %s \n", resultSTR);