1 /*
2 * Copyright (C) 2007, 2008 Apple Inc. All rights reserved.
3 * (C) 2008 Maksim Orlovich <maksim@kde.org>
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Library 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 * Library General Public License for more details.
14 *
15 * You should have received a copy of the GNU Library General Public License
16 * along with this library; see the file COPYING.LIB. If not, write to
17 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 * Boston, MA 02110-1301, USA.
19 *
20 * Portions of this code that are (C) 2007, 2008 Apple Inc. were
21 * originally distributed under the following terms
22 *
23 * Redistribution and use in source and binary forms, with or without
24 * modification, are permitted provided that the following conditions
25 * are met:
26 *
27 * 1. Redistributions of source code must retain the above copyright
28 * notice, this list of conditions and the following disclaimer.
29 * 2. Redistributions in binary form must reproduce the above copyright
30 * notice, this list of conditions and the following disclaimer in the
31 * documentation and/or other materials provided with the distribution.
32 * 3. Neither the name of Apple Computer, Inc. ("Apple") nor the names of
33 * its contributors may be used to endorse or promote products derived
34 * from this software without specific prior written permission.
35 *
36 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY
37 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
38 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
39 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
40 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
41 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
42 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
43 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
44 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
45 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
46 */
47
48 #ifndef JSVariableObject_h
49 #define JSVariableObject_h
50
51 #include "LocalStorage.h"
52 #include "SymbolTable.h"
53 #include "object.h"
54
55 #include <wtf/Vector.h>
56
57 namespace KJS
58 {
59 class Interpreter;
60
61 class JSVariableObject : public JSObject
62 {
63 public:
64 using KJS::JSObject::deleteProperty;
65 bool deleteProperty(ExecState *, const Identifier &) override;
66
67 void getOwnPropertyNames(ExecState *, PropertyNameArray &, PropertyMap::PropertyMode mode) override;
68
69 void mark() override;
70
71 enum {
72 LengthSlot,
73 TearOffNeeded, // Set when a tearoff is requested;
74 // the actual tearoff will only happen once the function
75 // stops running, though
76 ScopeLink,
77 NumVarObjectSlots = 3
78 };
79
lengthSlot()80 int32_t &lengthSlot()
81 {
82 return localStorage[LengthSlot].val.int32Val;
83 }
lengthSlot()84 const int32_t &lengthSlot() const
85 {
86 return localStorage[LengthSlot].val.int32Val;
87 }
88
tearOffNeededSlot()89 bool &tearOffNeededSlot()
90 {
91 return localStorage[TearOffNeeded].val.boolVal;
92 }
93
scopeLink()94 ScopeChainLink &scopeLink()
95 {
96 return localStorage[ScopeLink].val.scopeVal;
97 }
98 protected:
JSVariableObject()99 JSVariableObject(): localStorage(nullptr), symbolTable(nullptr) { }
100 ~JSVariableObject() override;
101
102 bool symbolTableGet(const Identifier &, PropertySlot &);
103 bool symbolTablePut(const Identifier &, JSValue *, bool checkReadOnly);
104
105 public:
106 LocalStorageEntry *localStorage; // Storage for variables in the symbol table.
107 SymbolTable *symbolTable; // Maps name -> index in localStorage.
108 };
109
symbolTableGet(const Identifier & propertyName,PropertySlot & slot)110 inline bool JSVariableObject::symbolTableGet(const Identifier &propertyName, PropertySlot &slot)
111 {
112 size_t index = symbolTable->get(propertyName.ustring().rep());
113 if (index != missingSymbolMarker()) {
114 slot.setValueSlot(this, &localStorage[index].val.valueVal);
115 return true;
116 }
117 return false;
118 }
119
symbolTablePut(const Identifier & propertyName,JSValue * value,bool checkReadOnly)120 inline bool JSVariableObject::symbolTablePut(const Identifier &propertyName, JSValue *value, bool checkReadOnly)
121 {
122 size_t index = symbolTable->get(propertyName.ustring().rep());
123 if (index == missingSymbolMarker()) {
124 return false;
125 }
126 LocalStorageEntry &entry = localStorage[index];
127 if (checkReadOnly && (entry.attributes & ReadOnly)) {
128 return true;
129 }
130 entry.val.valueVal = value;
131 return true;
132 }
133
~JSVariableObject()134 inline JSVariableObject::~JSVariableObject()
135 {
136 if (localStorage) {
137 scopeLink().deref();
138 if (tearOffNeededSlot()) {
139 delete[] localStorage;
140 }
141 }
142 }
143
object()144 inline JSObject *ScopeChainLink::object() const
145 {
146 if (isToScopeChainNode()) {
147 return asScopeChainNode()->object;
148 } else {
149 return asVariableObject();
150 }
151 }
152
next()153 inline ScopeChainLink ScopeChainLink::next() const
154 {
155 if (isToScopeChainNode()) {
156 return asScopeChainNode()->next;
157 } else {
158 return asVariableObject()->scopeLink();
159 }
160 }
161
mark()162 inline void ScopeChain::mark()
163 {
164 for (ScopeChainLink n = m_top; n.ptr; n = n.next()) {
165 JSObject *o = n.object();
166 if (!o->marked()) {
167 o->mark();
168 }
169 }
170 }
171
pushVariableObject(JSVariableObject * act)172 inline void ScopeChain::pushVariableObject(JSVariableObject *act)
173 {
174 // note: this assumes the new variable object is not in any
175 // scope chain in the moment.
176
177 // Set the item's next pointer to the current top.
178 // there is no refcount ops since it's transferring a reference
179 act->scopeLink() = m_top;
180
181 // new top!
182 m_top.set(act);
183 }
184
185 class KJS_EXPORT JSGlobalObject : public JSObject // ### TODO: should inherit off JSVariableObject
186 {
187 public:
JSGlobalObject()188 JSGlobalObject(): m_interpreter(nullptr) {}
JSGlobalObject(JSValue * proto)189 JSGlobalObject(JSValue *proto): JSObject(proto), m_interpreter(nullptr) {}
isGlobalObject()190 bool isGlobalObject() const override
191 {
192 return true;
193 }
194
setInterpreter(Interpreter * intp)195 void setInterpreter(Interpreter *intp)
196 {
197 m_interpreter = intp;
198 }
interpreter()199 Interpreter *interpreter() const
200 {
201 return m_interpreter;
202 }
203 private:
204 Interpreter *m_interpreter;
205 };
206 } // namespace KJS
207
208 #endif // JSVariableObject_h
209