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 | class Interpreter; |
59 | |
60 | class JSVariableObject : public JSObject { |
61 | public: |
62 | using KJS::JSObject::deleteProperty; |
63 | virtual bool deleteProperty(ExecState*, const Identifier&); |
64 | |
65 | virtual void getOwnPropertyNames(ExecState*, PropertyNameArray&, PropertyMap::PropertyMode mode); |
66 | |
67 | virtual void mark(); |
68 | |
69 | enum { |
70 | LengthSlot, |
71 | TearOffNeeded, // Set when a tearoff is requested; |
72 | // the actual tearoff will only happen once the function |
73 | // stops running, though |
74 | ScopeLink, |
75 | NumVarObjectSlots = 3 |
76 | }; |
77 | |
78 | int32_t& lengthSlot() { return localStorage[LengthSlot].val.int32Val; } |
79 | const int32_t& lengthSlot() const { return localStorage[LengthSlot].val.int32Val; } |
80 | |
81 | bool& tearOffNeededSlot() { return localStorage[TearOffNeeded].val.boolVal; } |
82 | |
83 | ScopeChainLink& scopeLink() { return localStorage[ScopeLink].val.scopeVal; } |
84 | protected: |
85 | JSVariableObject(): localStorage(0), symbolTable(0) { } |
86 | ~JSVariableObject(); |
87 | |
88 | bool symbolTableGet(const Identifier&, PropertySlot&); |
89 | bool symbolTablePut(const Identifier&, JSValue*, bool checkReadOnly); |
90 | |
91 | public: |
92 | LocalStorageEntry* localStorage; // Storage for variables in the symbol table. |
93 | SymbolTable* symbolTable; // Maps name -> index in localStorage. |
94 | }; |
95 | |
96 | inline bool JSVariableObject::symbolTableGet(const Identifier& propertyName, PropertySlot& slot) |
97 | { |
98 | size_t index = symbolTable->get(propertyName.ustring().rep()); |
99 | if (index != missingSymbolMarker()) { |
100 | slot.setValueSlot(this, &localStorage[index].val.valueVal); |
101 | return true; |
102 | } |
103 | return false; |
104 | } |
105 | |
106 | inline bool JSVariableObject::symbolTablePut(const Identifier& propertyName, JSValue* value, bool checkReadOnly) |
107 | { |
108 | size_t index = symbolTable->get(propertyName.ustring().rep()); |
109 | if (index == missingSymbolMarker()) |
110 | return false; |
111 | LocalStorageEntry& entry = localStorage[index]; |
112 | if (checkReadOnly && (entry.attributes & ReadOnly)) |
113 | return true; |
114 | entry.val.valueVal = value; |
115 | return true; |
116 | } |
117 | |
118 | inline JSVariableObject::~JSVariableObject() |
119 | { |
120 | if (localStorage) { |
121 | scopeLink().deref(); |
122 | if (tearOffNeededSlot()) |
123 | delete[] localStorage; |
124 | } |
125 | } |
126 | |
127 | inline JSObject* ScopeChainLink::object() const |
128 | { |
129 | if (isToScopeChainNode()) |
130 | return asScopeChainNode()->object; |
131 | else |
132 | return asVariableObject(); |
133 | } |
134 | |
135 | inline ScopeChainLink ScopeChainLink::next() const |
136 | { |
137 | if (isToScopeChainNode()) |
138 | return asScopeChainNode()->next; |
139 | else |
140 | return asVariableObject()->scopeLink(); |
141 | } |
142 | |
143 | inline void ScopeChain::mark() |
144 | { |
145 | for (ScopeChainLink n = m_top; n.ptr; n = n.next()) { |
146 | JSObject *o = n.object(); |
147 | if (!o->marked()) |
148 | o->mark(); |
149 | } |
150 | } |
151 | |
152 | inline void ScopeChain::pushVariableObject(JSVariableObject* act) |
153 | { |
154 | // note: this assumes the new variable object is not in any |
155 | // scope chain in the moment. |
156 | |
157 | // Set the item's next pointer to the current top. |
158 | // there is no refcount ops since it's transferring a reference |
159 | act->scopeLink() = m_top; |
160 | |
161 | // new top! |
162 | m_top.set(act); |
163 | } |
164 | |
165 | |
166 | class KJS_EXPORT JSGlobalObject : public JSObject // ### TODO: should inherit off JSVariableObject |
167 | { |
168 | public: |
169 | JSGlobalObject(): m_interpreter(0) {} |
170 | JSGlobalObject(JSValue* proto): JSObject(proto), m_interpreter(0) {} |
171 | virtual bool isGlobalObject() const { return true; } |
172 | |
173 | void setInterpreter(Interpreter* intp) { m_interpreter = intp; } |
174 | Interpreter* interpreter() const { return m_interpreter; } |
175 | private: |
176 | Interpreter* m_interpreter; |
177 | }; |
178 | } // namespace KJS |
179 | |
180 | #endif // JSVariableObject_h |
181 | // kate: indent-width 4; replace-tabs on; tab-width 4; space-indent on; |
182 | |