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

Add JSRT weak reference APIs #2948

Merged
merged 6 commits into from
May 11, 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
31 changes: 31 additions & 0 deletions bin/NativeTests/JsRTApiTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,37 @@ namespace JsRTApiTest
JsRTApiTest::RunWithAttributes(JsRTApiTest::ReferenceCountingTest);
}

void WeakReferenceTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
{
JsValueRef valueRef = JS_INVALID_REFERENCE;
REQUIRE(JsCreateString("test", strlen("test"), &valueRef) == JsNoError);

JsWeakRef weakRef = JS_INVALID_REFERENCE;
REQUIRE(JsCreateWeakReference(valueRef, &weakRef) == JsNoError);

// JsGetWeakReferenceValue should return the original value reference.
JsValueRef valueRefFromWeakRef = JS_INVALID_REFERENCE;
CHECK(JsGetWeakReferenceValue(weakRef, &valueRefFromWeakRef) == JsNoError);
CHECK(valueRefFromWeakRef != JS_INVALID_REFERENCE);
CHECK(valueRefFromWeakRef == valueRef);

// Clear the references on the stack, so that the value will be GC'd.
valueRef = JS_INVALID_REFERENCE;
valueRefFromWeakRef = JS_INVALID_REFERENCE;

CHECK(JsCollectGarbage(runtime) == JsNoError);

// JsGetWeakReferenceValue should return an invalid reference after the value was GC'd.
JsValueRef valueRefAfterGC = JS_INVALID_REFERENCE;
CHECK(JsGetWeakReferenceValue(weakRef, &valueRefAfterGC) == JsNoError);
CHECK(valueRefAfterGC == JS_INVALID_REFERENCE);
}

TEST_CASE("ApiTest_WeakReferenceTest", "[ApiTest]")
{
JsRTApiTest::RunWithAttributes(JsRTApiTest::WeakReferenceTest);
}

void ObjectsAndPropertiesTest1(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
{
JsValueRef object = JS_INVALID_REFERENCE;
Expand Down
46 changes: 42 additions & 4 deletions lib/Jsrt/ChakraCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -508,9 +508,47 @@ CHAKRA_API
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsCreatePromise(
_Out_ JsValueRef *promise,
_Out_ JsValueRef *resolveFunction,
_Out_ JsValueRef *rejectFunction);
JsCreatePromise(
_Out_ JsValueRef *promise,
_Out_ JsValueRef *resolveFunction,
_Out_ JsValueRef *rejectFunction);

/// <summary>
/// A weak reference to a JavaScript value.
/// </summary>
/// <remarks>
/// A value with only weak references is available for garbage-collection. A strong reference
/// to the value (<c>JsValueRef</c>) may be obtained from a weak reference if the value happens
/// to still be available.
/// </remarks>
typedef JsRef JsWeakRef;

/// <summary>
/// Creates a weak reference to a value.
/// </summary>
/// <param name="value">The value to be referenced.</param>
/// <param name="weakRef">Weak reference to the value.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsCreateWeakReference(
_In_ JsValueRef value,
_Out_ JsWeakRef* weakRef);

/// <summary>
/// Gets a strong reference to the value referred to by a weak reference.
/// </summary>
/// <param name="weakRef">A weak reference.</param>
/// <param name="value">Reference to the value, or <c>JS_INVALID_REFERENCE</c> if the value is
/// no longer available.</param>
/// <returns>
/// The code <c>JsNoError</c> if the operation succeeded, a failure code otherwise.
/// </returns>
CHAKRA_API
JsGetWeakReferenceValue(
_In_ JsWeakRef weakRef,
_Out_ JsValueRef* value);

#endif // CHAKRACOREBUILD_
#endif // _CHAKRACORE_H_
53 changes: 49 additions & 4 deletions lib/Jsrt/Jsrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -761,7 +761,7 @@ CHAKRA_API JsSetCurrentContext(_In_ JsContextRef newContext)
}
else
{
if(oldScriptContext->IsTTDRecordModeEnabled())
if(oldScriptContext->IsTTDRecordModeEnabled())
{
//already know newScriptContext != oldScriptContext so don't check again
if(oldScriptContext->ShouldPerformRecordAction())
Expand Down Expand Up @@ -3904,7 +3904,7 @@ CHAKRA_API JsTTDPreExecuteSnapShotInterval(_In_ JsRuntimeHandle runtimeHandle, _
return inflateStatus;
}

//If we are in the "active" segment set the continue breakpoint
//If we are in the "active" segment set the continue breakpoint
if((moveMode & JsTTDMoveMode::JsTTDMoveScanIntervalForContinueInActiveBreakpointSegment) == JsTTDMoveMode::JsTTDMoveScanIntervalForContinueInActiveBreakpointSegment)
{
GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode
Expand Down Expand Up @@ -3944,7 +3944,7 @@ CHAKRA_API JsTTDPreExecuteSnapShotInterval(_In_ JsRuntimeHandle runtimeHandle, _
elog->PopMode(TTD::TTDMode::DebuggerLogBreakpoints);
elog->PopMode(TTD::TTDMode::DebuggerSuppressBreakpoints);

//If we are in the "active" segment un-set the continue breakpoint
//If we are in the "active" segment un-set the continue breakpoint
if((moveMode & JsTTDMoveMode::JsTTDMoveScanIntervalForContinueInActiveBreakpointSegment) == JsTTDMoveMode::JsTTDMoveScanIntervalForContinueInActiveBreakpointSegment)
{
GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode
Expand Down Expand Up @@ -4036,7 +4036,7 @@ CHAKRA_API JsTTDReplayExecution(_Inout_ JsTTDMoveMode* moveMode, _Out_ int64_t*
return JsNoError;
});

if(bpstatus != JsNoError)
if(bpstatus != JsNoError)
{
return bpstatus;
}
Expand Down Expand Up @@ -4545,4 +4545,49 @@ CHAKRA_API JsCreatePromise(_Out_ JsValueRef *promise, _Out_ JsValueRef *resolve,
return JsNoError;
});
}

CHAKRA_API JsCreateWeakReference(
_In_ JsValueRef value,
_Out_ JsWeakRef* weakRef)
{
VALIDATE_JSREF(value);
PARAM_NOT_NULL(weakRef);
*weakRef = nullptr;

return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
ThreadContext* threadContext = ThreadContext::GetContextForCurrentThread();
if (threadContext == nullptr)
{
return JsErrorNoCurrentContext;
}

Recycler* recycler = threadContext->GetRecycler();
if (recycler->IsInObjectBeforeCollectCallback())
{
return JsErrorInObjectBeforeCollectCallback;
}

recycler->FindOrCreateWeakReferenceHandle<char>(
reinterpret_cast<char*>(value),
reinterpret_cast<Memory::RecyclerWeakReference<char>**>(weakRef));
return JsNoError;
});
}

CHAKRA_API JsGetWeakReferenceValue(
_In_ JsWeakRef weakRef,
_Out_ JsValueRef* value)
{
VALIDATE_JSREF(weakRef);
PARAM_NOT_NULL(value);
*value = JS_INVALID_REFERENCE;

return GlobalAPIWrapper_NoRecord([&]() -> JsErrorCode {
Memory::RecyclerWeakReference<char>* recyclerWeakReference =
reinterpret_cast<Memory::RecyclerWeakReference<char>*>(weakRef);
*value = reinterpret_cast<JsValueRef>(recyclerWeakReference->Get());
return JsNoError;
});
}

#endif // CHAKRACOREBUILD_
2 changes: 2 additions & 0 deletions lib/Jsrt/JsrtCommonExports.inc
Original file line number Diff line number Diff line change
Expand Up @@ -116,4 +116,6 @@
JsCreatePropertyId
JsCopyPropertyId
JsCreatePromise
JsCreateWeakReference
JsGetWeakReferenceValue
#endif