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 API JsLessThan (Fix #3568) #3931

Merged
merged 1 commit into from
Oct 18, 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
3 changes: 3 additions & 0 deletions bin/ChakraCore/ChakraCore.def
Original file line number Diff line number Diff line change
Expand Up @@ -55,3 +55,6 @@ JsInitializeJITServer
JsCreateSharedArrayBufferWithSharedContent
JsGetSharedArrayBufferContent
JsReleaseSharedArrayBufferContentHandle

JsLessThan
JsLessThanOrEqual
53 changes: 53 additions & 0 deletions bin/NativeTests/JsRTApiTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2196,4 +2196,57 @@ namespace JsRTApiTest
JsRTApiTest::RunWithAttributes(JsRTApiTest::JsCopyStringOneByteMethodTest);
}

void JsLessThanTest(JsRuntimeAttributes attributes, JsRuntimeHandle runtime)
{
// Create some values
JsValueRef number1 = JS_INVALID_REFERENCE; // number1 = 1
REQUIRE(JsDoubleToNumber(1, &number1) == JsNoError);
JsValueRef number2 = JS_INVALID_REFERENCE; // number2 = 2
REQUIRE(JsDoubleToNumber(2, &number2) == JsNoError);
JsValueRef stringa = JS_INVALID_REFERENCE; // stringa = "1"
REQUIRE(JsPointerToString(_u("1"), wcslen(_u("1")), &stringa) == JsNoError);
JsValueRef undefined = GetUndefined();
JsValueRef nullValue = JS_INVALID_REFERENCE;
REQUIRE(JsGetNullValue(&nullValue) == JsNoError);
JsValueRef trueValue = JS_INVALID_REFERENCE;
REQUIRE(JsGetTrueValue(&trueValue) == JsNoError);
JsValueRef falseValue = JS_INVALID_REFERENCE;
REQUIRE(JsGetFalseValue(&falseValue) == JsNoError);

bool result;
REQUIRE(JsLessThan(number1, number2, &result) == JsNoError);
CHECK(result == true);
REQUIRE(JsLessThan(number1, stringa, &result) == JsNoError);
CHECK(result == false);
REQUIRE(JsLessThan(number1, undefined, &result) == JsNoError);
CHECK(result == false);
REQUIRE(JsLessThan(falseValue, trueValue, &result) == JsNoError);
CHECK(result == true);
REQUIRE(JsLessThan(undefined, undefined, &result) == JsNoError);
CHECK(result == false);
REQUIRE(JsLessThan(nullValue, undefined, &result) == JsNoError);
CHECK(result == false);

REQUIRE(JsLessThanOrEqual(number1, number2, &result) == JsNoError);
CHECK(result == true);
REQUIRE(JsLessThanOrEqual(number1, number1, &result) == JsNoError);
CHECK(result == true);
REQUIRE(JsLessThanOrEqual(number1, stringa, &result) == JsNoError);
CHECK(result == true);
REQUIRE(JsLessThanOrEqual(trueValue, trueValue, &result) == JsNoError);
CHECK(result == true);
REQUIRE(JsLessThanOrEqual(falseValue, nullValue, &result) == JsNoError);
CHECK(result == true);
REQUIRE(JsLessThanOrEqual(falseValue, undefined, &result) == JsNoError);
CHECK(result == false);
REQUIRE(JsLessThanOrEqual(undefined, undefined, &result) == JsNoError);
CHECK(result == false);
REQUIRE(JsLessThanOrEqual(nullValue, undefined, &result) == JsNoError);
CHECK(result == false);
}

TEST_CASE("ApiTest_JsLessThanTest", "[ApiTest]")
{
JsRTApiTest::RunWithAttributes(JsRTApiTest::JsLessThanTest);
}
}
46 changes: 46 additions & 0 deletions lib/Jsrt/ChakraCore.h
Original file line number Diff line number Diff line change
Expand Up @@ -745,5 +745,51 @@ CHAKRA_API
_Out_opt_ unsigned int *byteOffset,
_Out_opt_ unsigned int *byteLength);

/// <summary>
/// Determine if one JavaScript value is less than another JavaScript value.
/// </summary>
/// <remarks>
/// <para>
/// This function is equivalent to the <c>&lt;</c> operator in Javascript.
/// </para>
/// <para>
/// Requires an active script context.
/// </para>
/// </remarks>
/// <param name="object1">The first object to compare.</param>
/// <param name="object2">The second object to compare.</param>
/// <param name="result">Whether object1 is less than object2.</param>
/// <returns>
/// 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);

/// <summary>
/// Determine if one JavaScript value is less than or equal to another JavaScript value.
/// </summary>
/// <remarks>
/// <para>
/// This function is equivalent to the <c>&lt;=</c> operator in Javascript.
/// </para>
/// <para>
/// Requires an active script context.
/// </para>
/// </remarks>
/// <param name="object1">The first object to compare.</param>
/// <param name="object2">The second object to compare.</param>
/// <param name="result">Whether object1 is less than or equal to object2.</param>
/// <returns>
/// 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);

#endif // _CHAKRACOREBUILD
#endif // _CHAKRACORE_H_
30 changes: 30 additions & 0 deletions lib/Jsrt/Jsrt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2221,6 +2221,36 @@ CHAKRA_API JsGetIndexedPropertiesExternalData(
END_JSRT_NO_EXCEPTION
}

CHAKRA_API JsLessThan(_In_ JsValueRef object1, _In_ JsValueRef object2, _Out_ bool *result)
{
return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTLessThan, object1, object2, false);

VALIDATE_INCOMING_REFERENCE(object1, scriptContext);
VALIDATE_INCOMING_REFERENCE(object2, scriptContext);
PARAM_NOT_NULL(result);

*result = Js::JavascriptOperators::Less((Js::Var)object1, (Js::Var)object2, scriptContext) != 0;

return JsNoError;
});
}

CHAKRA_API JsLessThanOrEqual(_In_ JsValueRef object1, _In_ JsValueRef object2, _Out_ bool *result)
{
return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&](Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTLessThan, object1, object2, true);

VALIDATE_INCOMING_REFERENCE(object1, scriptContext);
VALIDATE_INCOMING_REFERENCE(object2, scriptContext);
PARAM_NOT_NULL(result);

*result = Js::JavascriptOperators::LessEqual((Js::Var)object1, (Js::Var)object2, scriptContext) != 0;

return JsNoError;
});
}

CHAKRA_API JsEquals(_In_ JsValueRef object1, _In_ JsValueRef object2, _Out_ bool *result)
{
return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
Expand Down
20 changes: 20 additions & 0 deletions lib/Runtime/Debug/TTActionEvents.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -536,6 +536,26 @@ namespace TTD
}
}

void LessThanAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
{
TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
const JsRTDoubleVarSingleScalarArgumentAction* action = GetInlineEventDataAs<JsRTDoubleVarSingleScalarArgumentAction, EventKind::LessThanActionTag>(evt);
Js::Var object1 = InflateVarInReplay(executeContext, GetVarItem_0(action));
TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object1, ctx);
Js::Var object2 = InflateVarInReplay(executeContext, GetVarItem_1(action));
TTD_REPLAY_VALIDATE_INCOMING_REFERENCE(object2, ctx);

//Result is not needed but trigger computation for any effects
if (GetScalarItem_0(action))
{
Js::JavascriptOperators::LessEqual(object1, object2, ctx);
}
else
{
Js::JavascriptOperators::Less(object1, object2, ctx);
}
}

void GetPropertyIdFromSymbolAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext)
{
TTD_REPLAY_ACTIVE_CONTEXT(executeContext);
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Debug/TTActionEvents.h
Original file line number Diff line number Diff line change
Expand Up @@ -492,6 +492,7 @@ namespace TTD
void HasOwnPropertyAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void InstanceOfAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void EqualsAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);
void LessThanAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);

void GetPropertyIdFromSymbolAction_Execute(const EventLogEntry* evt, ThreadContextTTD* executeContext);

Expand Down
12 changes: 12 additions & 0 deletions lib/Runtime/Debug/TTEventLog.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,7 @@ namespace TTD
TTD_CREATE_EVENTLIST_VTABLE_ENTRY_COMMON(HasOwnPropertyActionTag, ContextAPIWrapper, JsRTSingleVarScalarArgumentAction, HasOwnPropertyAction_Execute);
TTD_CREATE_EVENTLIST_VTABLE_ENTRY_COMMON(InstanceOfActionTag, ContextAPIWrapper, JsRTDoubleVarArgumentAction, InstanceOfAction_Execute);
TTD_CREATE_EVENTLIST_VTABLE_ENTRY_COMMON(EqualsActionTag, ContextAPIWrapper, JsRTDoubleVarSingleScalarArgumentAction, EqualsAction_Execute);
TTD_CREATE_EVENTLIST_VTABLE_ENTRY_COMMON(LessThanActionTag, ContextAPIWrapper, JsRTDoubleVarSingleScalarArgumentAction, LessThanAction_Execute);

TTD_CREATE_EVENTLIST_VTABLE_ENTRY_COMMON(GetPropertyIdFromSymbolTag, ContextAPINoScriptWrapper, JsRTSingleVarArgumentAction, GetPropertyIdFromSymbolAction_Execute);

Expand Down Expand Up @@ -2200,6 +2201,17 @@ namespace TTD
actionPopper.InitializeWithEventAndEnter(evt);
}

void EventLog::RecordJsRTLessThan(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var1, Js::Var var2, bool allowsEqual)
{
NSLogEvents::JsRTDoubleVarSingleScalarArgumentAction* gpAction = nullptr;
NSLogEvents::EventLogEntry* evt = this->RecordGetInitializedEvent<NSLogEvents::JsRTDoubleVarSingleScalarArgumentAction, NSLogEvents::EventKind::LessThanActionTag>(&gpAction);
NSLogEvents::SetVarItem_0(gpAction, TTD_CONVERT_JSVAR_TO_TTDVAR(var1));
NSLogEvents::SetVarItem_1(gpAction, TTD_CONVERT_JSVAR_TO_TTDVAR(var2));
NSLogEvents::SetScalarItem_0(gpAction, allowsEqual);

actionPopper.InitializeWithEventAndEnter(evt);
}

void EventLog::RecordJsRTGetPropertyIdFromSymbol(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var sym)
{
NSLogEvents::JsRTSingleVarArgumentAction* gpAction = nullptr;
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Debug/TTEventLog.h
Original file line number Diff line number Diff line change
Expand Up @@ -560,6 +560,7 @@ namespace TTD
void RecordJsRTHasOwnProperty(TTDJsRTActionResultAutoRecorder& actionPopper, const Js::PropertyRecord* pRecord, Js::Var var);
void RecordJsRTInstanceOf(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var object, Js::Var constructor);
void RecordJsRTEquals(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var1, Js::Var var2, bool doStrict);
void RecordJsRTLessThan(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var var1, Js::Var var2, bool allowsEqual);

//Record getters with native results
void RecordJsRTGetPropertyIdFromSymbol(TTDJsRTActionResultAutoRecorder& actionPopper, Js::Var sym);
Expand Down
1 change: 1 addition & 0 deletions lib/Runtime/Debug/TTEvents.h
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,7 @@ namespace TTD
HasPropertyActionTag,
InstanceOfActionTag,
EqualsActionTag,
LessThanActionTag,

GetPropertyIdFromSymbolTag,

Expand Down