Skip to content
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
38 changes: 38 additions & 0 deletions bin/NativeTests/JsRTApiTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,44 @@ namespace JsRTApiTest
JsRTApiTest::RunWithAttributes(JsRTApiTest::DeleteObjectIndexedPropertyBug);
}

void HasOwnItemTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
{
JsValueRef object;
REQUIRE(JsRunScript(_u("var obj = {a: [1,2], \"1\": 111}; obj.__proto__[3] = 333; obj;"), JS_SOURCE_CONTEXT_NONE, _u(""), &object) == JsNoError);

JsPropertyIdRef idRef = JS_INVALID_REFERENCE;
JsValueRef result = JS_INVALID_REFERENCE;
// delete property "a" triggers PathTypeHandler -> SimpleDictionaryTypeHandler
REQUIRE(JsGetPropertyIdFromName(_u("a"), &idRef) == JsNoError);
REQUIRE(JsGetProperty(object, idRef, &result) == JsNoError);
bool hasOwnItem = false;
REQUIRE(JsHasOwnItem(result, 0, &hasOwnItem) == JsNoError);
CHECK(hasOwnItem);

REQUIRE(JsHasOwnItem(result, 1, &hasOwnItem) == JsNoError);
CHECK(hasOwnItem);

REQUIRE(JsHasOwnItem(result, 2, &hasOwnItem) == JsNoError);
CHECK(!hasOwnItem); // It does not have item on index 2 - so we should not be able to find that.

REQUIRE(JsHasOwnItem(object, 1, &hasOwnItem) == JsNoError);
CHECK(hasOwnItem);

REQUIRE(JsHasOwnItem(object, 3, &hasOwnItem) == JsNoError);
CHECK(!hasOwnItem); // index 3 is on prototype.

bool has = false;
JsValueRef indexRef = JS_INVALID_REFERENCE;
REQUIRE(JsIntToNumber(3, &indexRef) == JsNoError);
REQUIRE(JsHasIndexedProperty(object, indexRef, &has) == JsNoError);
CHECK(has); // index 3 is prototype - so it should be able to find that.
}

TEST_CASE("ApiTest_HasOwnItemTest", "[ApiTest]")
{
JsRTApiTest::RunWithAttributes(JsRTApiTest::HasOwnItemTest);
}

void CALLBACK ExternalObjectFinalizeCallback(void *data)
{
CHECK(data == (void *)0xdeadbeef);
Expand Down
19 changes: 19 additions & 0 deletions lib/Jsrt/ChakraCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -961,6 +961,25 @@ CHAKRA_API
_Out_ bool *hasOwnProperty);

/// <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 item.</param>
/// <param name="index">The index to find.</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
JsHasOwnItem(
_In_ JsValueRef object,
_In_ uint32_t index,
_Out_ bool* hasOwnItem);

/// <summary>
/// Write JS string value into char string buffer without a null terminator
/// </summary>
/// <remarks>
Expand Down
19 changes: 19 additions & 0 deletions lib/Jsrt/Core/JsrtCore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -516,6 +516,25 @@ JsExternalizeArrayBuffer(
});
}

CHAKRA_API
JsHasOwnItem(_In_ JsValueRef object,
_In_ uint32_t index,
_Out_ bool* hasOwnItem)
{
return ContextAPIWrapper<true>(
[&](Js::ScriptContext* scriptContext,
TTDRecorder& _actionEntryPopper) -> JsErrorCode {

VALIDATE_INCOMING_OBJECT(object, scriptContext);
PARAM_NOT_NULL(hasOwnItem);

*hasOwnItem = !!Js::JavascriptOperators::HasOwnItem(
Js::VarTo<Js::RecyclableObject>(object), index);

return JsNoError;
});
}

CHAKRA_API
JsDetachArrayBuffer(
_In_ JsValueRef arrayBuffer)
Expand Down
1 change: 1 addition & 0 deletions lib/Jsrt/JsrtCommonExports.inc
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
JsGetPropertyIdSymbolIterator
JsGetWeakReferenceValue
JsHasOwnProperty
JsHasOwnItem
JsIsConstructor
JsObjectDefineProperty
JsObjectDefinePropertyFull
Expand Down