Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

jsrt: JsObject Delete/Get/Has/OwnP../Set Property #3875

Merged
merged 2 commits into from
Nov 6, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 51 additions & 18 deletions lib/Common/Codex/Utf8Helper.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,30 +86,28 @@ namespace utf8
return WideStringToNarrow(Allocator::allocate, sourceString, sourceCount, destStringPtr, destCount, allocateCount);
}

///
/// Use the codex library to encode a UTF8 string to UTF16.
/// The caller is responsible for freeing the memory, which is allocated
/// using Allocator.
/// The returned string is null terminated.
///
template <typename AllocatorFunction>
HRESULT NarrowStringToWide(_In_ AllocatorFunction allocator,_In_ LPCSTR sourceString, size_t sourceCount, _Out_ LPWSTR* destStringPtr, _Out_ size_t* destCount, size_t* allocateCount = nullptr)
inline HRESULT NarrowStringToWideNoAlloc(_In_ LPCSTR sourceString, size_t sourceCount,
__out_ecount(destBufferCount) LPWSTR destString, size_t destBufferCount, _Out_ size_t* destCount)
{
size_t cbSourceString = sourceCount;
size_t sourceStart = 0;
size_t cbDestString = (sourceCount + 1) * sizeof(WCHAR);
if (cbDestString < sourceCount) // overflow ?
size_t cbSourceString = sourceCount;

if (sourceCount >= MAXUINT32)
{
destString[0] = WCHAR(0);
return E_OUTOFMEMORY;
}

WCHAR* destString = (WCHAR*)allocator(cbDestString);
if (destString == nullptr)
{
return E_OUTOFMEMORY;
return E_INVALIDARG;
}

if (allocateCount != nullptr) *allocateCount = cbDestString;
if (sourceCount >= destBufferCount)
{
destString[0] = WCHAR(0);
return E_INVALIDARG;
}

for (; sourceStart < sourceCount; sourceStart++)
{
Expand All @@ -127,7 +125,6 @@ namespace utf8
{
*destCount = sourceCount;
destString[sourceCount] = WCHAR(0);
*destStringPtr = destString;
}
else
{
Expand All @@ -136,20 +133,56 @@ namespace utf8

charcount_t cchDestString = utf8::ByteIndexIntoCharacterIndex(remSourceString, cbSourceString - sourceStart);
cchDestString += (charcount_t)sourceStart;
Assert (cchDestString <= sourceCount);
if (cchDestString > sourceCount)
{
return E_OUTOFMEMORY;
}

// Some node tests depend on the utf8 decoder not swallowing invalid unicode characters
// instead of replacing them with the "replacement" chracter. Pass a flag to our
// decoder to require such behavior
utf8::DecodeUnitsIntoAndNullTerminateNoAdvance(remDestString, remSourceString, (LPCUTF8) sourceString + cbSourceString, DecodeOptions::doAllowInvalidWCHARs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The assert just before here that cchDestString <= sourceCount should be cchDestString <= destBufferCount I believe (maybe strictly less to allow for the null terminator), and if this function is exposed outside of our code then I think it should be an if(...) { return E_OUTOFMEMORY;} and not an assert.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not sure.. This PR didn't make any logical changes within the Utf8Helper stuff. Just split an existing interface for reuse purposes.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added if (cchDestString > sourceCount)

Assert(destString[cchDestString] == 0);

static_assert(sizeof(utf8char_t) == sizeof(char), "Needs to be valid for cast");
*destStringPtr = destString;
*destCount = cchDestString;
}

Assert(destString[*destCount] == 0);

return S_OK;
}

///
/// Use the codex library to encode a UTF8 string to UTF16.
/// The caller is responsible for freeing the memory, which is allocated
/// using Allocator.
/// The returned string is null terminated.
///
template <typename AllocatorFunction>
HRESULT NarrowStringToWide(_In_ AllocatorFunction allocator,_In_ LPCSTR sourceString,
size_t sourceCount, _Out_ LPWSTR* destStringPtr, _Out_ size_t* destCount, size_t* allocateCount = nullptr)
{
size_t cbDestString = (sourceCount + 1) * sizeof(WCHAR);
if (cbDestString < sourceCount) // overflow ?
{
return E_OUTOFMEMORY;
}

WCHAR* destString = (WCHAR*)allocator(cbDestString);
if (destString == nullptr)
{
return E_OUTOFMEMORY;
}

if (allocateCount != nullptr)
{
*allocateCount = cbDestString;
}

*destStringPtr = destString;
return NarrowStringToWideNoAlloc(sourceString, sourceCount, destString, sourceCount + 1, destCount);
}

template <class Allocator>
HRESULT NarrowStringToWide(_In_ LPCSTR sourceString, size_t sourceCount, _Out_ LPWSTR* destStringPtr, _Out_ size_t* destCount, size_t* allocateCount = nullptr)
{
Expand Down
147 changes: 139 additions & 8 deletions lib/Jsrt/ChakraCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -764,10 +764,10 @@ CHAKRA_API
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsLessThan(
_In_ JsValueRef object1,
_In_ JsValueRef object2,
_Out_ bool *result);
JsLessThan(
_In_ JsValueRef object1,
_In_ JsValueRef object2,
_Out_ bool *result);

/// <summary>
/// Determine if one JavaScript value is less than or equal to another JavaScript value.
Expand All @@ -787,10 +787,141 @@ JsLessThan(
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsLessThanOrEqual(
_In_ JsValueRef object1,
_In_ JsValueRef object2,
_Out_ bool *result);
JsLessThanOrEqual(
_In_ JsValueRef object1,
_In_ JsValueRef object2,
_Out_ bool *result);

/// <summary>
/// Gets an object's property.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="object">The object that contains the property.</param>
/// <param name="key">The key (JavascriptString) to the property.</param>
/// <param name="value">The value of the property.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsObjectGetProperty(
_In_ JsValueRef object,
_In_ JsValueRef key,
_Out_ JsValueRef *value);

/// <summary>
/// Puts an object's property.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="object">The object that contains the property.</param>
/// <param name="key">The key (JavascriptString) to the property.</param>
/// <param name="value">The new value of the property.</param>
/// <param name="useStrictRules">The property set should follow strict mode rules.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsObjectSetProperty(
_In_ JsValueRef object,
_In_ JsValueRef key,
_In_ JsValueRef value,
_In_ bool useStrictRules);

/// <summary>
/// Determines whether an object has a property.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="object">The object that may contain the property.</param>
/// <param name="key">The key (JavascriptString) to the property.</param>
/// <param name="hasProperty">Whether the object (or a prototype) has the property.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsObjectHasProperty(
_In_ JsValueRef object,
_In_ JsValueRef key,
_Out_ bool *hasProperty);

/// <summary>
/// Defines a new object's own property from a property descriptor.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="object">The object that has the property.</param>
/// <param name="key">The key (JavascriptString) to the property.</param>
/// <param name="propertyDescriptor">The property descriptor.</param>
/// <param name="result">Whether the property was defined.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsObjectDefineProperty(
_In_ JsValueRef object,
_In_ JsValueRef key,
_In_ JsValueRef propertyDescriptor,
_Out_ bool *result);

/// <summary>
/// Deletes an object's property.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="object">The object that contains the property.</param>
/// <param name="key">The key (JavascriptString) to the property.</param>
/// <param name="useStrictRules">The property set should follow strict mode rules.</param>
/// <param name="result">Whether the property was deleted.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsObjectDeleteProperty(
_In_ JsValueRef object,
_In_ JsValueRef key,
_In_ bool useStrictRules,
_Out_ JsValueRef *result);

/// <summary>
/// Gets a property descriptor for an object's own property.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="object">The object that has the property.</param>
/// <param name="key">The key (JavascriptString) to the property.</param>
/// <param name="propertyDescriptor">The property descriptor.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsObjectGetOwnPropertyDescriptor(
_In_ JsValueRef object,
_In_ JsValueRef key,
_Out_ JsValueRef *propertyDescriptor);

/// <summary>
/// Determines whether an object has a non-inherited property.
/// </summary>
/// <remarks>
/// Requires an active script context.
/// </remarks>
/// <param name="object">The object that may contain the property.</param>
/// <param name="key">The key (JavascriptString) to the property.</param>
/// <param name="hasOwnProperty">Whether the object has the non-inherited property.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsObjectHasOwnProperty(
_In_ JsValueRef object,
_In_ JsValueRef key,
_Out_ bool *hasOwnProperty);
#endif // _CHAKRACOREBUILD
#endif // _CHAKRACORE_H_
Loading