1 | /* |
2 | * Copyright (C) 1999-2000 Harri Porten ([email protected]) |
3 | * Copyright (C) 2007-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 "JSWrapperObject.h" |
24 | #include "JSString.h" |
25 | |
26 | namespace JSC { |
27 | |
28 | class StringObject : public JSWrapperObject { |
29 | public: |
30 | using Base = JSWrapperObject; |
31 | static constexpr unsigned StructureFlags = Base::StructureFlags | OverridesGetOwnPropertySlot | InterceptsGetOwnPropertySlotByIndexEvenWhenLengthIsNotZero | OverridesGetPropertyNames; |
32 | |
33 | static StringObject* create(VM& vm, Structure* structure) |
34 | { |
35 | JSString* string = jsEmptyString(vm); |
36 | StringObject* object = new (NotNull, allocateCell<StringObject>(vm.heap)) StringObject(vm, structure); |
37 | object->finishCreation(vm, string); |
38 | return object; |
39 | } |
40 | static StringObject* create(VM& vm, Structure* structure, JSString* string) |
41 | { |
42 | StringObject* object = new (NotNull, allocateCell<StringObject>(vm.heap)) StringObject(vm, structure); |
43 | object->finishCreation(vm, string); |
44 | return object; |
45 | } |
46 | static StringObject* create(VM&, JSGlobalObject*, JSString*); |
47 | |
48 | JS_EXPORT_PRIVATE static bool getOwnPropertySlot(JSObject*, JSGlobalObject*, PropertyName, PropertySlot&); |
49 | JS_EXPORT_PRIVATE static bool getOwnPropertySlotByIndex(JSObject*, JSGlobalObject*, unsigned propertyName, PropertySlot&); |
50 | |
51 | JS_EXPORT_PRIVATE static bool put(JSCell*, JSGlobalObject*, PropertyName, JSValue, PutPropertySlot&); |
52 | JS_EXPORT_PRIVATE static bool putByIndex(JSCell*, JSGlobalObject*, unsigned propertyName, JSValue, bool shouldThrow); |
53 | |
54 | JS_EXPORT_PRIVATE static bool deleteProperty(JSCell*, JSGlobalObject*, PropertyName); |
55 | JS_EXPORT_PRIVATE static bool deletePropertyByIndex(JSCell*, JSGlobalObject*, unsigned propertyName); |
56 | JS_EXPORT_PRIVATE static void getOwnPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode); |
57 | JS_EXPORT_PRIVATE static void getOwnNonIndexPropertyNames(JSObject*, JSGlobalObject*, PropertyNameArray&, EnumerationMode); |
58 | JS_EXPORT_PRIVATE static bool defineOwnProperty(JSObject*, JSGlobalObject*, PropertyName, const PropertyDescriptor&, bool shouldThrow); |
59 | |
60 | DECLARE_EXPORT_INFO; |
61 | |
62 | JSString* internalValue() const { return asString(JSWrapperObject::internalValue()); } |
63 | |
64 | static Structure* createStructure(VM& vm, JSGlobalObject* globalObject, JSValue prototype) |
65 | { |
66 | return Structure::create(vm, globalObject, prototype, TypeInfo(StringObjectType, StructureFlags), info()); |
67 | } |
68 | |
69 | protected: |
70 | JS_EXPORT_PRIVATE void finishCreation(VM&, JSString*); |
71 | JS_EXPORT_PRIVATE StringObject(VM&, Structure*); |
72 | }; |
73 | |
74 | JS_EXPORT_PRIVATE StringObject* constructString(VM&, JSGlobalObject*, JSValue); |
75 | |
76 | // Helper for producing a JSString for 'string', where 'string' was been produced by |
77 | // calling ToString on 'originalValue'. In cases where 'originalValue' already was a |
78 | // string primitive we can just use this, otherwise we need to allocate a new JSString. |
79 | // FIXME: Basically any use of this is bad. toString() returns a JSString* so we don't need to |
80 | // pass around the originalValue; we could just pass around the JSString*. Then you don't need |
81 | // this function. You just use the JSString* that toString() returned. |
82 | static inline JSString* jsStringWithReuse(JSGlobalObject* globalObject, JSValue originalValue, const String& string) |
83 | { |
84 | if (originalValue.isString()) { |
85 | ASSERT(asString(originalValue)->value(globalObject) == string); |
86 | return asString(originalValue); |
87 | } |
88 | return jsString(getVM(globalObject), string); |
89 | } |
90 | |
91 | // Helper that tries to use the JSString substring sharing mechanism if 'originalValue' is a JSString. |
92 | // FIXME: Basically any use of this is bad. toString() returns a JSString* so we don't need to |
93 | // pass around the originalValue; we could just pass around the JSString*. And since we've |
94 | // resolved it, we know that we can just allocate the substring cell directly. |
95 | // https://bugs.webkit.org/show_bug.cgi?id=158140 |
96 | static inline JSString* jsSubstring(JSGlobalObject* globalObject, JSValue originalValue, const String& string, unsigned offset, unsigned length) |
97 | { |
98 | if (originalValue.isString()) { |
99 | ASSERT(asString(originalValue)->value(globalObject) == string); |
100 | return jsSubstring(globalObject, asString(originalValue), offset, length); |
101 | } |
102 | return jsSubstring(getVM(globalObject), string, offset, length); |
103 | } |
104 | |
105 | } // namespace JSC |
106 | |