StackTraceArguments.cpp 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeLanguagePch.h"
  6. namespace Js {
  7. uint64 StackTraceArguments::ObjectToTypeCode(Js::Var object)
  8. {
  9. switch(JavascriptOperators::GetTypeId(object))
  10. {
  11. case TypeIds_Null:
  12. return nullValue;
  13. case TypeIds_Undefined:
  14. return undefinedValue;
  15. case TypeIds_Boolean:
  16. return booleanValue;
  17. case TypeIds_String:
  18. return stringValue;
  19. case TypeIds_Symbol:
  20. return symbolValue;
  21. case TypeIds_Number:
  22. if (Js::JavascriptNumber::IsNan(JavascriptNumber::GetValue(object)))
  23. {
  24. return nanValue;
  25. }
  26. else
  27. {
  28. return numberValue;
  29. }
  30. case TypeIds_Integer:
  31. case TypeIds_Int64Number:
  32. case TypeIds_UInt64Number:
  33. return numberValue;
  34. }
  35. return objectValue;
  36. }
  37. JavascriptString *StackTraceArguments::TypeCodeToTypeName(unsigned typeCode, ScriptContext *scriptContext)
  38. {
  39. switch(typeCode)
  40. {
  41. case nullValue:
  42. return scriptContext->GetLibrary()->GetNullDisplayString();
  43. case undefinedValue:
  44. return scriptContext->GetLibrary()->GetUndefinedDisplayString();
  45. case booleanValue:
  46. return scriptContext->GetLibrary()->GetBooleanTypeDisplayString();
  47. case stringValue:
  48. return scriptContext->GetLibrary()->GetStringTypeDisplayString();
  49. case nanValue:
  50. return scriptContext->GetLibrary()->GetNaNDisplayString();
  51. case numberValue:
  52. return scriptContext->GetLibrary()->GetNumberTypeDisplayString();
  53. case symbolValue:
  54. return scriptContext->GetLibrary()->GetSymbolTypeDisplayString();
  55. case objectValue:
  56. return scriptContext->GetLibrary()->GetObjectTypeDisplayString();
  57. default:
  58. AssertMsg(0, "Unknown type code");
  59. return scriptContext->GetLibrary()->GetEmptyString();
  60. }
  61. }
  62. void StackTraceArguments::Init(const JavascriptStackWalker &walker)
  63. {
  64. types = 0;
  65. if (!walker.IsCallerGlobalFunction())
  66. {
  67. const CallInfo callInfo = walker.GetCallInfo();
  68. int64 numberOfArguments = callInfo.Count;
  69. if (numberOfArguments > 0) numberOfArguments --; // Don't consider 'this'
  70. if (callInfo.Flags & Js::CallFlags_ExtraArg)
  71. {
  72. Assert(numberOfArguments > 0 );
  73. // skip the last FrameDisplay argument.
  74. numberOfArguments--;
  75. }
  76. for (int64 j = 0; j < numberOfArguments && j < MaxNumberOfDisplayedArgumentsInStack; j ++)
  77. {
  78. types |= ObjectToTypeCode(walker.GetJavascriptArgs()[j]) << 3*j; // maximal code is 7, so we can use 3 bits to store it
  79. }
  80. if (numberOfArguments > MaxNumberOfDisplayedArgumentsInStack)
  81. {
  82. types |= fTooManyArgs; // two upper bits are flags
  83. }
  84. }
  85. else
  86. {
  87. types |= fCallerIsGlobal; // two upper bits are flags
  88. }
  89. }
  90. HRESULT StackTraceArguments::ToString(LPCWSTR functionName, Js::ScriptContext *scriptContext, _In_ LPCWSTR *outResult) const
  91. {
  92. HRESULT hr = S_OK;
  93. uint64 argumentsTypes = types;
  94. BEGIN_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT_NESTED
  95. {
  96. CompoundString *const stringBuilder = CompoundString::NewWithCharCapacity(40, scriptContext->GetLibrary());
  97. stringBuilder->AppendCharsSz(functionName);
  98. bool calleIsGlobalFunction = (argumentsTypes & fCallerIsGlobal) != 0;
  99. bool toManyArgs = (argumentsTypes & fTooManyArgs) != 0;
  100. argumentsTypes &= ~fCallerIsGlobal; // erase flags to prevent them from being treated as values
  101. argumentsTypes &= ~fTooManyArgs;
  102. if (!calleIsGlobalFunction)
  103. {
  104. stringBuilder->AppendChars(_u('('));
  105. }
  106. for (uint64 i = 0; i < MaxNumberOfDisplayedArgumentsInStack && argumentsTypes != 0; i ++)
  107. {
  108. if (i > 0)
  109. {
  110. stringBuilder->AppendChars(_u(", "));
  111. }
  112. stringBuilder->AppendChars(TypeCodeToTypeName(argumentsTypes & 7, scriptContext)); // we use 3 bits to store one code
  113. argumentsTypes >>= 3;
  114. }
  115. if (toManyArgs)
  116. {
  117. stringBuilder->AppendChars(_u(", ..."));
  118. }
  119. if (!calleIsGlobalFunction)
  120. {
  121. stringBuilder->AppendChars(_u(')'));
  122. }
  123. *outResult = stringBuilder->GetString();
  124. }
  125. END_TRANSLATE_EXCEPTION_AND_ERROROBJECT_TO_HRESULT(hr);
  126. return hr;
  127. }
  128. }