1 | /* |
2 | * Copyright (C) 1999-2000 Harri Porten ([email protected]) |
3 | * Copyright (C) 2003-2019 Apple Inc. All Rights Reserved. |
4 | * |
5 | * This library is free software; you can redistribute it and/or |
6 | * modify it under the terms of the GNU Lesser General Public |
7 | * License as published by the Free Software Foundation; either |
8 | * version 2 of the License, or (at your option) any later version. |
9 | * |
10 | * This library is distributed in the hope that it will be useful, |
11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
13 | * Lesser General Public License for more details. |
14 | * |
15 | * You should have received a copy of the GNU Lesser General Public |
16 | * License along with this library; if not, write to the Free Software |
17 | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
18 | * |
19 | */ |
20 | |
21 | #pragma once |
22 | |
23 | #include "JSObject.h" |
24 | #include "RegExp.h" |
25 | #include "ThrowScope.h" |
26 | #include "TypeError.h" |
27 | |
28 | namespace JSC { |
29 | |
30 | class RegExpObject final : public JSNonFinalObject { |
31 | public: |
32 | using Base = JSNonFinalObject; |
33 | static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | OverridesGetPropertyNames; |
34 | |
35 | static constexpr uintptr_t lastIndexIsNotWritableFlag = 1; |
36 | |
37 | static RegExpObject* create(VM& vm, Structure* structure, RegExp* regExp) |
38 | { |
39 | RegExpObject* object = new (NotNull, allocateCell<RegExpObject>(vm.heap)) RegExpObject(vm, structure, regExp); |
40 | object->finishCreation(vm); |
41 | return object; |
42 | } |
43 | |
44 | static RegExpObject* create(VM& vm, Structure* structure, RegExp* regExp, JSValue lastIndex) |
45 | { |
46 | auto* object = create(vm, structure, regExp); |
47 | object->m_lastIndex.set(vm, object, lastIndex); |
48 | return object; |
49 | } |
50 | |
51 | void setRegExp(VM& vm, RegExp* regExp) |
52 | { |
53 | uintptr_t result = (m_regExpAndLastIndexIsNotWritableFlag & lastIndexIsNotWritableFlag) | bitwise_cast<uintptr_t>(regExp); |
54 | m_regExpAndLastIndexIsNotWritableFlag = result; |
55 | vm.heap.writeBarrier(this, regExp); |
56 | } |
57 | |
58 | RegExp* regExp() const |
59 | { |
60 | return bitwise_cast<RegExp*>(m_regExpAndLastIndexIsNotWritableFlag & (~lastIndexIsNotWritableFlag)); |
61 | } |
62 | |
63 | bool setLastIndex(JSGlobalObject* globalObject, size_t lastIndex) |
64 | { |
65 | VM& vm = getVM(globalObject); |
66 | auto scope = DECLARE_THROW_SCOPE(vm); |
67 | |
68 | if (LIKELY(lastIndexIsWritable())) { |
69 | m_lastIndex.setWithoutWriteBarrier(jsNumber(lastIndex)); |
70 | return true; |
71 | } |
72 | throwTypeError(globalObject, scope, ReadonlyPropertyWriteError); |
73 | return false; |
74 | } |
75 | bool setLastIndex(JSGlobalObject* globalObject, JSValue lastIndex, bool shouldThrow) |
76 | { |
77 | VM& vm = getVM(globalObject); |
78 | auto scope = DECLARE_THROW_SCOPE(vm); |
79 | |
80 | if (LIKELY(lastIndexIsWritable())) { |
81 | m_lastIndex.set(vm, this, lastIndex); |
82 | return true; |
83 | } |
84 | return typeError(globalObject, scope, shouldThrow, ReadonlyPropertyWriteError); |
85 | } |
86 | JSValue getLastIndex() const |
87 | { |
88 | return m_lastIndex.get(); |
89 | } |
90 | |
91 | bool test(JSGlobalObject* globalObject, JSString* string) { return !!match(globalObject, string); } |
92 | bool testInline(JSGlobalObject* globalObject, JSString* string) { return !!matchInline(globalObject, string); } |
93 | JSValue exec(JSGlobalObject*, JSString*); |
94 | JSValue execInline(JSGlobalObject*, JSString*); |
95 | MatchResult match(JSGlobalObject*, JSString*); |
96 | JSValue matchGlobal(JSGlobalObject*, JSString*); |
97 | |
98 | static bool getOwnPropertySlot(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&); |
99 | static bool put(JSCell*, JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); |
100 | |
101 | DECLARE_EXPORT_INFO; |
102 | |
103 | static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) |
104 | { |
105 | return Structure::create(vm, globalObject, prototype, TypeInfo(RegExpObjectType, StructureFlags), info()); |
106 | } |
107 | |
108 | static ptrdiff_t offsetOfRegExpAndLastIndexIsNotWritableFlag() |
109 | { |
110 | return OBJECT_OFFSETOF(RegExpObject, m_regExpAndLastIndexIsNotWritableFlag); |
111 | } |
112 | |
113 | static ptrdiff_t offsetOfLastIndex() |
114 | { |
115 | return OBJECT_OFFSETOF(RegExpObject, m_lastIndex); |
116 | } |
117 | |
118 | static size_t allocationSize(Checked<size_t> inlineCapacity) |
119 | { |
120 | ASSERT_UNUSED(inlineCapacity, !inlineCapacity); |
121 | return sizeof(RegExpObject); |
122 | } |
123 | |
124 | protected: |
125 | JS_EXPORT_PRIVATE RegExpObject(VM&, Structure*, RegExp*); |
126 | JS_EXPORT_PRIVATE void finishCreation(VM&); |
127 | |
128 | static void visitChildren(JSCell*, SlotVisitor&); |
129 | |
130 | bool lastIndexIsWritable() const |
131 | { |
132 | return !(m_regExpAndLastIndexIsNotWritableFlag & lastIndexIsNotWritableFlag); |
133 | } |
134 | |
135 | void setLastIndexIsNotWritable() |
136 | { |
137 | m_regExpAndLastIndexIsNotWritableFlag = (m_regExpAndLastIndexIsNotWritableFlag | lastIndexIsNotWritableFlag); |
138 | } |
139 | |
140 | JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName); |
141 | JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode); |
142 | JS_EXPORT_PRIVATE static void getPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode); |
143 | JS_EXPORT_PRIVATE static void getGenericPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode); |
144 | JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, JSGlobalObject*, PropertyName, const PropertyDescriptor&, bool shouldThrow); |
145 | |
146 | private: |
147 | MatchResult matchInline(JSGlobalObject*, JSString*); |
148 | |
149 | uintptr_t m_regExpAndLastIndexIsNotWritableFlag { 0 }; |
150 | WriteBarrier<Unknown> m_lastIndex; |
151 | }; |
152 | |
153 | } // namespace JSC |
154 | |