Преглед изворни кода

[1.9>master] [MERGE #4591 @kfarnung] Fixing TTD regressions from JsObject* function refactor

Merge pull request #4591 from kfarnung:ttdobjects

When the JsObject* functions were added to JSRT there was an attempt
to refactor the TTD instrumentation into a common method. The
refactor caused a regression in cross-context scenarios where the
record was capturing both the result of the function as well as any
marshalling necessary to get the result.

This change reverts the behavior of the existing methods (e.g.
JsSetProperty and friends) to capture the record before any marshalling
can occur (VALIDATE_INCOMING_OBJECT will marshal the object if
necessary). For the new JsObject* functions I've added an assert to
ensure that once they are used they will cause TTD record to fail with
an actionable message.
Kyle Farnung пре 8 година
родитељ
комит
bdae93eff7
1 измењених фајлова са 47 додато и 44 уклоњено
  1. 47 44
      lib/Jsrt/Jsrt.cpp

+ 47 - 44
lib/Jsrt/Jsrt.cpp

@@ -1421,11 +1421,8 @@ CHAKRA_API JsPreventExtension(_In_ JsValueRef object)
 }
 
 CHAKRA_API JsHasOwnPropertyCommon(Js::ScriptContext * scriptContext, _In_ JsValueRef object,
-    _In_ const Js::PropertyRecord * propertyRecord, _Out_ bool *hasOwnProperty,
-    TTDRecorder& _actionEntryPopper)
+    _In_ const Js::PropertyRecord * propertyRecord, _Out_ bool *hasOwnProperty)
 {
-    PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTHasOwnProperty, propertyRecord, object);
-
     *hasOwnProperty = Js::JavascriptOperators::OP_HasOwnProperty(object,
         propertyRecord->GetPropertyId(), scriptContext) != 0;
 
@@ -1437,6 +1434,7 @@ CHAKRA_API JsHasOwnProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propert
 {
     return ContextAPIWrapper<true>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTHasOwnProperty, (const Js::PropertyRecord *)propertyId, object);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_PROPERTYID(propertyId);
@@ -1444,7 +1442,7 @@ CHAKRA_API JsHasOwnProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propert
         *hasOwnProperty = false;
 
         return JsHasOwnPropertyCommon(scriptContext, object,
-            (const Js::PropertyRecord *)propertyId, hasOwnProperty, _actionEntryPopper);
+            (const Js::PropertyRecord *)propertyId, hasOwnProperty);
     });
 }
 
@@ -1475,6 +1473,7 @@ CHAKRA_API JsObjectHasOwnProperty(_In_ JsValueRef object, _In_ JsValueRef proper
 {
     return ContextAPIWrapper<true>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_RECYCLABLE(propertyId, scriptContext);
@@ -1490,24 +1489,20 @@ CHAKRA_API JsObjectHasOwnProperty(_In_ JsValueRef object, _In_ JsValueRef proper
             return errorValue;
         }
 
-        return JsHasOwnPropertyCommon(scriptContext, object, propertyRecord, hasOwnProperty, _actionEntryPopper);
+        return JsHasOwnPropertyCommon(scriptContext, object, propertyRecord, hasOwnProperty);
     });
 }
 #endif
 
 static JsErrorCode JsGetPropertyCommon(Js::ScriptContext * scriptContext,
     _In_ Js::RecyclableObject * object,
-    _In_ const Js::PropertyRecord * propertyRecord, _Out_ JsValueRef *value,
-    TTDRecorder& _actionEntryPopper)
+    _In_ const Js::PropertyRecord * propertyRecord, _Out_ JsValueRef *value)
 {
     AssertMsg(scriptContext->GetThreadContext()->IsScriptActive(), "Caller is expected to be under ContextAPIWrapper!");
-    PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTGetProperty, propertyRecord, object);
 
     *value = Js::JavascriptOperators::GetPropertyNoCache(object, propertyRecord->GetPropertyId(), scriptContext);
     Assert(*value == nullptr || !Js::CrossSite::NeedMarshalVar(*value, scriptContext));
 
-    PERFORM_JSRT_TTD_RECORD_ACTION_RESULT(scriptContext, value);
-
     return JsNoError;
 }
 
@@ -1515,6 +1510,7 @@ CHAKRA_API JsGetProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propertyId
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTGetProperty, (const Js::PropertyRecord *)propertyId, object);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_PROPERTYID(propertyId);
@@ -1522,8 +1518,12 @@ CHAKRA_API JsGetProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propertyId
         *value = nullptr;
 
         Js::RecyclableObject * instance = Js::RecyclableObject::FromVar(object);
-        return JsGetPropertyCommon(scriptContext, instance, (const Js::PropertyRecord *)propertyId,
-             value, _actionEntryPopper);
+        JsErrorCode err = JsGetPropertyCommon(scriptContext, instance, (const Js::PropertyRecord *)propertyId,
+             value);
+
+        PERFORM_JSRT_TTD_RECORD_ACTION_RESULT(scriptContext, value);
+
+        return err;
     });
 }
 
@@ -1532,6 +1532,7 @@ CHAKRA_API JsObjectGetProperty(_In_ JsValueRef object, _In_ JsValueRef propertyI
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_RECYCLABLE(propertyId, scriptContext);
@@ -1550,17 +1551,15 @@ CHAKRA_API JsObjectGetProperty(_In_ JsValueRef object, _In_ JsValueRef propertyI
         Assert(propertyRecord != nullptr);
 
         Js::RecyclableObject * instance = Js::RecyclableObject::FromVar(object);
-        return JsGetPropertyCommon(scriptContext, instance, propertyRecord, value, _actionEntryPopper);
+        return JsGetPropertyCommon(scriptContext, instance, propertyRecord, value);
     });
 }
 #endif
 
 static JsErrorCode JsGetOwnPropertyDescriptorCommon(Js::ScriptContext * scriptContext,
-    _In_ JsValueRef object, _In_ const Js::PropertyRecord * propertyRecord, _Out_ JsValueRef *propertyDescriptor,
-    TTDRecorder& _actionEntryPopper)
+    _In_ JsValueRef object, _In_ const Js::PropertyRecord * propertyRecord, _Out_ JsValueRef *propertyDescriptor)
 {
     AssertMsg(scriptContext->GetThreadContext()->IsScriptActive(), "Caller is expected to be under ContextAPIWrapper!");
-    PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTGetOwnPropertyInfo, propertyRecord, object);
 
     Js::PropertyDescriptor propertyDescriptorValue;
     if (Js::JavascriptOperators::GetOwnPropertyDescriptor(Js::RecyclableObject::FromVar(object),
@@ -1574,21 +1573,25 @@ static JsErrorCode JsGetOwnPropertyDescriptorCommon(Js::ScriptContext * scriptCo
     }
     Assert(*propertyDescriptor == nullptr || !Js::CrossSite::NeedMarshalVar(*propertyDescriptor, scriptContext));
 
-    PERFORM_JSRT_TTD_RECORD_ACTION_RESULT(scriptContext, propertyDescriptor);
-
     return JsNoError;
 }
 
 CHAKRA_API JsGetOwnPropertyDescriptor(_In_ JsValueRef object, _In_ JsPropertyIdRef propertyId, _Out_ JsValueRef *propertyDescriptor)
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTGetOwnPropertyInfo, (const Js::PropertyRecord *)propertyId, object);
+
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_PROPERTYID(propertyId);
         PARAM_NOT_NULL(propertyDescriptor);
         *propertyDescriptor = nullptr;
 
-        return JsGetOwnPropertyDescriptorCommon(scriptContext, object, (const Js::PropertyRecord *)propertyId,
-            propertyDescriptor, _actionEntryPopper);
+        JsErrorCode err = JsGetOwnPropertyDescriptorCommon(scriptContext, object, (const Js::PropertyRecord *)propertyId,
+            propertyDescriptor);
+
+        PERFORM_JSRT_TTD_RECORD_ACTION_RESULT(scriptContext, propertyDescriptor);
+
+        return err;
     });
 }
 
@@ -1597,6 +1600,7 @@ CHAKRA_API JsObjectGetOwnPropertyDescriptor(_In_ JsValueRef object, _In_ JsValue
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_RECYCLABLE(propertyId, scriptContext);
@@ -1614,18 +1618,15 @@ CHAKRA_API JsObjectGetOwnPropertyDescriptor(_In_ JsValueRef object, _In_ JsValue
 
         Assert(propertyRecord != nullptr);
 
-        return JsGetOwnPropertyDescriptorCommon(scriptContext, object, propertyRecord, propertyDescriptor, _actionEntryPopper);
+        return JsGetOwnPropertyDescriptorCommon(scriptContext, object, propertyRecord, propertyDescriptor);
     });
 }
 #endif
 
 static JsErrorCode JsSetPropertyCommon(Js::ScriptContext * scriptContext, _In_ JsValueRef object,
-    _In_ const Js::PropertyRecord * propertyRecord, _In_ JsValueRef value, _In_ bool useStrictRules,
-    TTDRecorder& _actionEntryPopper)
+    _In_ const Js::PropertyRecord * propertyRecord, _In_ JsValueRef value, _In_ bool useStrictRules)
 {
     AssertMsg(scriptContext->GetThreadContext()->IsScriptActive(), "Caller is expected to be under ContextAPIWrapper!");
-    PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTSetProperty, object,
-        propertyRecord, value, useStrictRules);
 
     Js::JavascriptOperators::OP_SetProperty(object, propertyRecord->GetPropertyId(),
         value, scriptContext, nullptr, useStrictRules ? Js::PropertyOperation_StrictMode : Js::PropertyOperation_None);
@@ -1637,13 +1638,14 @@ CHAKRA_API JsSetProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propertyId
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTSetProperty, object, (const Js::PropertyRecord *)propertyId, value, useStrictRules);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_PROPERTYID(propertyId);
         VALIDATE_INCOMING_REFERENCE(value, scriptContext);
 
         return JsSetPropertyCommon(scriptContext, object, (const Js::PropertyRecord *)propertyId,
-            value, useStrictRules, _actionEntryPopper);
+            value, useStrictRules);
     });
 }
 
@@ -1652,6 +1654,7 @@ CHAKRA_API JsObjectSetProperty(_In_ JsValueRef object, _In_ JsValueRef propertyI
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_RECYCLABLE(propertyId, scriptContext);
@@ -1668,7 +1671,7 @@ CHAKRA_API JsObjectSetProperty(_In_ JsValueRef object, _In_ JsValueRef propertyI
 
         Assert(propertyRecord != nullptr);
 
-        return JsSetPropertyCommon(scriptContext, object, propertyRecord, value, useStrictRules, _actionEntryPopper);
+        return JsSetPropertyCommon(scriptContext, object, propertyRecord, value, useStrictRules);
     });
 }
 #endif
@@ -1717,6 +1720,7 @@ CHAKRA_API JsObjectHasProperty(_In_ JsValueRef object, _In_ JsValueRef propertyI
     if (!Js::JavascriptOperators::IsObject(object)) return JsErrorArgumentNotObject;
 
     auto internalHasProperty = [&] (Js::ScriptContext *scriptContext, TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_RECYCLABLE(propertyId, scriptContext);
         PARAM_NOT_NULL(hasProperty);
@@ -1731,8 +1735,6 @@ CHAKRA_API JsObjectHasProperty(_In_ JsValueRef object, _In_ JsValueRef propertyI
             return errorValue;
         }
 
-        PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTHasProperty, propertyRecord, object);
-
         Js::RecyclableObject * instance = Js::RecyclableObject::FromVar(object);
         *hasProperty = Js::JavascriptOperators::HasProperty(instance, propertyRecord->GetPropertyId()) != 0;
 
@@ -1759,12 +1761,9 @@ CHAKRA_API JsObjectHasProperty(_In_ JsValueRef object, _In_ JsValueRef propertyI
 #endif
 
 static JsErrorCode JsDeletePropertyCommon(Js::ScriptContext * scriptContext, _In_ JsValueRef object,
-    _In_ const Js::PropertyRecord * propertyRecord, _In_ bool useStrictRules, _Out_ JsValueRef *result,
-    TTDRecorder& _actionEntryPopper)
+    _In_ const Js::PropertyRecord * propertyRecord, _In_ bool useStrictRules, _Out_ JsValueRef *result)
 {
     AssertMsg(scriptContext->GetThreadContext()->IsScriptActive(), "Caller is expected to be under ContextAPIWrapper!");
-    PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTDeleteProperty, object,
-        propertyRecord, useStrictRules);
 
     *result = Js::JavascriptOperators::OP_DeleteProperty((Js::Var)object,
         propertyRecord->GetPropertyId(),
@@ -1772,8 +1771,6 @@ static JsErrorCode JsDeletePropertyCommon(Js::ScriptContext * scriptContext, _In
 
     Assert(*result == nullptr || !Js::CrossSite::NeedMarshalVar(*result, scriptContext));
 
-    PERFORM_JSRT_TTD_RECORD_ACTION_RESULT(scriptContext, result);
-
     return JsNoError;
 }
 
@@ -1782,14 +1779,19 @@ CHAKRA_API JsDeleteProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propert
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTDeleteProperty, object, (const Js::PropertyRecord *)propertyId, useStrictRules);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_PROPERTYID(propertyId);
         PARAM_NOT_NULL(result);
         *result = nullptr;
 
-        return JsDeletePropertyCommon(scriptContext, object, (const Js::PropertyRecord *)propertyId,
-            useStrictRules, result, _actionEntryPopper);
+        JsErrorCode err = JsDeletePropertyCommon(scriptContext, object, (const Js::PropertyRecord *)propertyId,
+            useStrictRules, result);
+
+        PERFORM_JSRT_TTD_RECORD_ACTION_RESULT(scriptContext, result);
+
+        return err;
     });
 }
 
@@ -1799,6 +1801,7 @@ CHAKRA_API JsObjectDeleteProperty(_In_ JsValueRef object, _In_ JsValueRef proper
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_RECYCLABLE(propertyId, scriptContext);
@@ -1817,18 +1820,16 @@ CHAKRA_API JsObjectDeleteProperty(_In_ JsValueRef object, _In_ JsValueRef proper
         Assert(propertyRecord != nullptr);
 
         return JsDeletePropertyCommon(scriptContext, object, propertyRecord,
-            useStrictRules, result, _actionEntryPopper);
+            useStrictRules, result);
     });
 }
 #endif
 
 static JsErrorCode JsDefinePropertyCommon(Js::ScriptContext * scriptContext, _In_ JsValueRef object,
     _In_ const Js::PropertyRecord *propertyRecord, _In_ JsValueRef propertyDescriptor,
-    _Out_ bool *result, TTDRecorder& _actionEntryPopper)
+    _Out_ bool *result)
 {
     AssertMsg(scriptContext->GetThreadContext()->IsScriptActive(), "Caller is expected to be under ContextAPIWrapper!");
-    PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTDefineProperty, object,
-        propertyRecord, propertyDescriptor);
 
     Js::PropertyDescriptor propertyDescriptorValue;
     if (!Js::JavascriptOperators::ToPropertyDescriptor(propertyDescriptor, &propertyDescriptorValue, scriptContext))
@@ -1848,6 +1849,7 @@ CHAKRA_API JsDefineProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propert
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION(scriptContext, RecordJsRTDefineProperty, object, (const Js::PropertyRecord *)propertyId, propertyDescriptor);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_PROPERTYID(propertyId);
@@ -1856,7 +1858,7 @@ CHAKRA_API JsDefineProperty(_In_ JsValueRef object, _In_ JsPropertyIdRef propert
         *result = false;
 
         return JsDefinePropertyCommon(scriptContext, object, (const Js::PropertyRecord *)propertyId,
-            propertyDescriptor, result, _actionEntryPopper);
+            propertyDescriptor, result);
     });
 }
 
@@ -1866,6 +1868,7 @@ CHAKRA_API JsObjectDefineProperty(_In_ JsValueRef object, _In_ JsValueRef proper
 {
     return ContextAPIWrapper<JSRT_MAYBE_TRUE>([&] (Js::ScriptContext *scriptContext,
         TTDRecorder& _actionEntryPopper) -> JsErrorCode {
+        PERFORM_JSRT_TTD_RECORD_ACTION_NOT_IMPLEMENTED(scriptContext);
 
         VALIDATE_INCOMING_OBJECT(object, scriptContext);
         VALIDATE_INCOMING_RECYCLABLE(propertyId, scriptContext);
@@ -1882,7 +1885,7 @@ CHAKRA_API JsObjectDefineProperty(_In_ JsValueRef object, _In_ JsValueRef proper
             return errorValue;
         }
 
-        return JsDefinePropertyCommon(scriptContext, object, propertyRecord, propertyDescriptor, result, _actionEntryPopper);
+        return JsDefinePropertyCommon(scriptContext, object, propertyRecord, propertyDescriptor, result);
     });
 }
 #endif