JavascriptRegularExpression.h 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  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. #pragma once
  6. namespace Js
  7. {
  8. class JavascriptRegExp : public DynamicObject
  9. {
  10. friend class JavascriptRegularExpressionType;
  11. friend class RegexHelper;
  12. private:
  13. static PropertyId const specialPropertyIdsAll[];
  14. static PropertyId const specialPropertyIdsWithoutUnicode[];
  15. static PropertyId const specialPropertyIdsWithoutDotAll[];
  16. static PropertyId const specialPropertyIdsWithoutDotAllOrUnicode[];
  17. static const uint defaultSpecialPropertyIdsCount = 6;
  18. Field(UnifiedRegex::RegexPattern*) pattern;
  19. // The pattern used by String.prototype.split could be different than the normal pattern. Even
  20. // when the sticky flag is present in the normal pattern, split() should look for the pattern
  21. // in the whole input string as opposed to just looking for it at the beginning.
  22. //
  23. // Initialization of this pattern is deferred until split() is called, or it's copied from another
  24. // RegExp object.
  25. Field(UnifiedRegex::RegexPattern*) splitPattern;
  26. Field(Var) lastIndexVar; // null => must build lastIndexVar from current lastIndex
  27. public:
  28. // Three states for lastIndex value:
  29. // 1. lastIndexVar has been updated, we must calculate lastIndex from it when we next need it
  30. static const CharCount NotCachedValue = (CharCount)-2;
  31. private:
  32. // 2. ToNumber(lastIndexVar) yields +inf or -inf or an integer not in range [0, MaxCharCount]
  33. static const CharCount InvalidValue = CharCountFlag;
  34. // 3. ToNumber(lastIndexVar) yields NaN, +0, -0 or an integer in range [0, MaxCharCount]
  35. Field(CharCount) lastIndexOrFlag;
  36. static JavascriptRegExp * GetJavascriptRegExp(Arguments& args, PCWSTR varName, ScriptContext* scriptContext);
  37. static JavascriptRegExp * ToRegExp(Var var, PCWSTR varName, ScriptContext* scriptContext);
  38. static RecyclableObject * GetThisObject(Arguments& args, PCWSTR varName, ScriptContext* scriptContext);
  39. static JavascriptString * GetFirstStringArg(Arguments& args, ScriptContext* scriptContext);
  40. static bool ShouldApplyPrototypeWebWorkaround(Arguments& args, ScriptContext* scriptContext);
  41. bool GetPropertyBuiltIns(PropertyId propertyId, Var* value, BOOL* result);
  42. bool SetPropertyBuiltIns(PropertyId propertyId, Var value, PropertyOperationFlags flags, BOOL* result);
  43. bool GetSetterBuiltIns(PropertyId propertyId, PropertyValueInfo* info, DescriptorFlags* result);
  44. inline PropertyId const * GetSpecialPropertyIdsInlined() const;
  45. Var GetOptions();
  46. void SetPattern(UnifiedRegex::RegexPattern* pattern)
  47. {
  48. this->pattern = pattern;
  49. }
  50. void SetSplitPattern(UnifiedRegex::RegexPattern* splitPattern)
  51. {
  52. this->splitPattern = splitPattern;
  53. }
  54. static CharCount GetLastIndexProperty(RecyclableObject* instance, ScriptContext* scriptContext);
  55. static void SetLastIndexProperty(Var instance, CharCount lastIndex, ScriptContext* scriptContext);
  56. static void SetLastIndexProperty(Var instance, Var lastIndex, ScriptContext* scriptContext);
  57. static bool GetGlobalProperty(RecyclableObject* instance, ScriptContext* scriptContext);
  58. static bool GetUnicodeProperty(RecyclableObject* instance, ScriptContext* scriptContext);
  59. static CharCount AddIndex(CharCount base, CharCount offset);
  60. static CharCount GetIndexOrMax(int64 index);
  61. static bool HasOriginalRegExType(RecyclableObject* instance);
  62. static bool HasObservableConstructor(DynamicObject* regexPrototype);
  63. static bool HasObservableExec(DynamicObject* regexPrototype);
  64. static bool HasObservableFlags(DynamicObject* regexPrototype);
  65. static bool HasObservableGlobalFlag(DynamicObject* regexPrototype);
  66. static bool HasObservableUnicodeFlag(DynamicObject* regexPrototype);
  67. static Var CallExec(RecyclableObject* thisObj, JavascriptString* string, PCWSTR varName, ScriptContext* scriptContext);
  68. UnifiedRegex::RegexFlags SetRegexFlag(PropertyId propertyId, UnifiedRegex::RegexFlags flags, UnifiedRegex::RegexFlags flag, ScriptContext* scriptContext);
  69. // For boxing stack instance
  70. JavascriptRegExp(JavascriptRegExp * instance, bool deepCopy);
  71. DEFINE_MARSHAL_OBJECT_TO_SCRIPT_CONTEXT(JavascriptRegExp);
  72. protected:
  73. DEFINE_VTABLE_CTOR(JavascriptRegExp, DynamicObject);
  74. public:
  75. JavascriptRegExp(UnifiedRegex::RegexPattern* pattern, DynamicType* type);
  76. JavascriptRegExp(DynamicType * type);
  77. static uint GetOffsetOfPattern() { return offsetof(JavascriptRegExp, pattern); }
  78. static uint GetOffsetOfSplitPattern() { return offsetof(JavascriptRegExp, splitPattern); }
  79. static uint GetOffsetOfLastIndexVar() { return offsetof(JavascriptRegExp, lastIndexVar); }
  80. static uint GetOffsetOfLastIndexOrFlag() { return offsetof(JavascriptRegExp, lastIndexOrFlag); }
  81. inline UnifiedRegex::RegexPattern* GetPattern() const { return pattern; }
  82. inline UnifiedRegex::RegexPattern* GetSplitPattern() const { return splitPattern; }
  83. InternalString GetSource() const;
  84. UnifiedRegex::RegexFlags GetFlags() const;
  85. void CacheLastIndex();
  86. inline CharCountOrFlag GetLastIndex()
  87. {
  88. if (lastIndexOrFlag == NotCachedValue)
  89. {
  90. CacheLastIndex();
  91. }
  92. return lastIndexOrFlag;
  93. }
  94. inline void SetLastIndex(CharCount lastIndex)
  95. {
  96. Assert(lastIndex <= MaxCharCount);
  97. lastIndexVar = nullptr;
  98. this->lastIndexOrFlag = lastIndex;
  99. }
  100. static bool IsRegExpLike(Var aValue, ScriptContext* scriptContext);
  101. static JavascriptRegExp* CreateRegEx(const char16* pSource, CharCount sourceLen,
  102. UnifiedRegex::RegexFlags flags, ScriptContext *scriptContext);
  103. static JavascriptRegExp* CreateRegEx(Var aValue, Var options, ScriptContext *scriptContext);
  104. static JavascriptRegExp* CreateRegExNoCoerce(Var aValue, Var options, ScriptContext *scriptContext);
  105. static UnifiedRegex::RegexPattern* CreatePattern(Var aValue, Var options, ScriptContext *scriptContext);
  106. static Var OP_NewRegEx(UnifiedRegex::RegexPattern* aCompiledRegex, ScriptContext* scriptContext);
  107. JavascriptString *ToString(bool sourceOnly = false);
  108. class EntryInfo
  109. {
  110. public:
  111. static FunctionInfo NewInstance;
  112. static FunctionInfo Exec;
  113. static FunctionInfo Test;
  114. static FunctionInfo ToString;
  115. static FunctionInfo SymbolMatch;
  116. static FunctionInfo SymbolReplace;
  117. static FunctionInfo SymbolSearch;
  118. static FunctionInfo SymbolSplit;
  119. static FunctionInfo GetterSymbolSpecies;
  120. static FunctionInfo GetterGlobal;
  121. static FunctionInfo GetterFlags;
  122. static FunctionInfo GetterIgnoreCase;
  123. static FunctionInfo GetterMultiline;
  124. static FunctionInfo GetterOptions;
  125. static FunctionInfo GetterSource;
  126. static FunctionInfo GetterSticky;
  127. static FunctionInfo GetterUnicode;
  128. static FunctionInfo GetterDotAll;
  129. // v5.8 only
  130. static FunctionInfo Compile;
  131. };
  132. static Var NewInstance(RecyclableObject* function, CallInfo callInfo, ...);
  133. static Var EntryExec(RecyclableObject* function, CallInfo callInfo, ...);
  134. static Var EntryTest(RecyclableObject* function, CallInfo callInfo, ...);
  135. static Var EntryToString(RecyclableObject* function, CallInfo callInfo, ...);
  136. static Var EntrySymbolMatch(RecyclableObject* function, CallInfo callInfo, ...);
  137. static Var EntrySymbolReplace(RecyclableObject* function, CallInfo callInfo, ...);
  138. static Var EntrySymbolSearch(RecyclableObject* function, CallInfo callInfo, ...);
  139. static Var EntrySymbolSplit(RecyclableObject* function, CallInfo callInfo, ...);
  140. static Var EntryGetterSymbolSpecies(RecyclableObject* function, CallInfo callInfo, ...);
  141. static Var EntryGetterFlags(RecyclableObject* function, CallInfo callInfo, ...);
  142. static void AppendFlagForFlagsProperty(StringBuilder<ArenaAllocator>* builder, RecyclableObject* thisObj, PropertyId propertyId, char16 flag, ScriptContext* scriptContext);
  143. static Var EntryGetterGlobal(RecyclableObject* function, CallInfo callInfo, ...);
  144. static Var EntryGetterIgnoreCase(RecyclableObject* function, CallInfo callInfo, ...);
  145. static Var EntryGetterMultiline(RecyclableObject* function, CallInfo callInfo, ...);
  146. static Var EntryGetterOptions(RecyclableObject* function, CallInfo callInfo, ...);
  147. static Var EntryGetterSource(RecyclableObject* function, CallInfo callInfo, ...);
  148. static Var EntryGetterSticky(RecyclableObject* function, CallInfo callInfo, ...);
  149. static Var EntryGetterUnicode(RecyclableObject* function, CallInfo callInfo, ...);
  150. static Var EntryGetterDotAll(RecyclableObject* function, CallInfo callInfo, ...);
  151. // v5.8 only
  152. static Var EntryCompile(RecyclableObject* function, CallInfo callInfo, ...);
  153. virtual bool HasReadOnlyPropertiesInvisibleToTypeHandler() override { return true; }
  154. virtual PropertyQueryFlags HasPropertyQuery(PropertyId propertyId, _Inout_opt_ PropertyValueInfo* info) override;
  155. virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  156. virtual PropertyQueryFlags GetPropertyQuery(Var originalInstance, JavascriptString* propertyNameString, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  157. virtual PropertyQueryFlags GetPropertyReferenceQuery(Var originalInstance, PropertyId propertyId, Var* value, PropertyValueInfo* info, ScriptContext* requestContext) override;
  158. virtual BOOL SetProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  159. virtual BOOL SetProperty(JavascriptString* propertyNameString, Var value, PropertyOperationFlags flags, PropertyValueInfo* info) override;
  160. virtual BOOL InitProperty(PropertyId propertyId, Var value, PropertyOperationFlags flags = PropertyOperation_None, PropertyValueInfo* info = NULL) override;
  161. virtual BOOL DeleteProperty(PropertyId propertyId, PropertyOperationFlags flags) override;
  162. virtual BOOL DeleteProperty(JavascriptString *propertyNameString, PropertyOperationFlags flags) override;
  163. virtual DescriptorFlags GetSetter(PropertyId propertyId, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
  164. virtual DescriptorFlags GetSetter(JavascriptString* propertyNameString, Var* setterValue, PropertyValueInfo* info, ScriptContext* requestContext) override;
  165. virtual BOOL GetDiagValueString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  166. virtual BOOL GetDiagTypeString(StringBuilder<ArenaAllocator>* stringBuilder, ScriptContext* requestContext) override;
  167. virtual BOOL IsEnumerable(PropertyId propertyId) override;
  168. virtual BOOL IsConfigurable(PropertyId propertyId) override;
  169. virtual BOOL IsWritable(PropertyId propertyId) override;
  170. virtual BOOL GetSpecialPropertyName(uint32 index, JavascriptString ** propertyName, ScriptContext * requestContext) override;
  171. virtual uint GetSpecialPropertyCount() const override;
  172. virtual PropertyId const * GetSpecialPropertyIds() const override;
  173. static Js::JavascriptRegExp * BoxStackInstance(Js::JavascriptRegExp * instance, bool deepCopy);
  174. #if ENABLE_TTD
  175. public:
  176. virtual TTD::NSSnapObjects::SnapObjectType GetSnapTag_TTD() const override;
  177. virtual void ExtractSnapObjectDataInto(TTD::NSSnapObjects::SnapObject* objData, TTD::SlabAllocator& alloc) override;
  178. void SetLastIndexInfo_TTD(CharCount lastIndex, Js::Var lastVar);
  179. #endif
  180. public:
  181. virtual VTableValue DummyVirtualFunctionToHinderLinkerICF()
  182. {
  183. return VTableValue::VtableJavascriptRegExp;
  184. }
  185. };
  186. template <> inline bool VarIsImpl<JavascriptRegExp>(RecyclableObject* obj)
  187. {
  188. return JavascriptOperators::GetTypeId(obj) == TypeIds_RegEx;
  189. }
  190. } // namespace Js