Not reviewed.
[WebKit-https.git] / Source / JavaScriptCore / runtime / JSScope.h
1 /*
2  * Copyright (C) 2012 Apple Inc. All Rights Reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
7  * 1. Redistributions of source code must retain the above copyright
8  *    notice, this list of conditions and the following disclaimer.
9  * 2. Redistributions in binary form must reproduce the above copyright
10  *    notice, this list of conditions and the following disclaimer in the
11  *    documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
17  * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18  * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19  * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20  * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21  * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
24  */
25
26 #ifndef JSScope_h
27 #define JSScope_h
28
29 #include "JSObject.h"
30
31 namespace JSC {
32
33 class ScopeChainIterator;
34
35 class JSScope : public JSNonFinalObject {
36 public:
37     typedef JSNonFinalObject Base;
38
39     friend class LLIntOffsetsExtractor;
40     static size_t offsetOfNext();
41
42     JS_EXPORT_PRIVATE static JSObject* objectAtScope(JSScope*);
43
44     static JSValue resolve(CallFrame*, const Identifier&);
45     static JSValue resolveSkip(CallFrame*, const Identifier&, int skip);
46     static JSValue resolveGlobal(
47         CallFrame*,
48         const Identifier&,
49         JSGlobalObject* globalObject,
50         WriteBarrierBase<Structure>* cachedStructure,
51         PropertyOffset* cachedOffset
52     );
53     static JSValue resolveGlobalDynamic(
54         CallFrame*,
55         const Identifier&,
56         int skip,
57         WriteBarrierBase<Structure>* cachedStructure,
58         PropertyOffset* cachedOffset
59     );
60     static JSValue resolveBase(CallFrame*, const Identifier&, bool isStrict);
61     static JSValue resolveWithBase(CallFrame*, const Identifier&, Register* base);
62     static JSValue resolveWithThis(CallFrame*, const Identifier&, Register* base);
63
64     static void visitChildren(JSCell*, SlotVisitor&);
65
66     bool isDynamicScope(bool& requiresDynamicChecks) const;
67
68     ScopeChainIterator begin();
69     ScopeChainIterator end();
70     JSScope* next();
71     int localDepth();
72
73     JSGlobalObject* globalObject();
74     JSGlobalData* globalData();
75     JSObject* globalThis();
76     void setGlobalThis(JSGlobalData&, JSObject*);
77
78 protected:
79     JSScope(JSGlobalData&, Structure*, JSGlobalObject*, JSObject* globalThis, JSScope* next);
80     static const unsigned StructureFlags = OverridesVisitChildren | Base::StructureFlags;
81
82 private:
83     JSGlobalData* m_globalData;
84     WriteBarrier<JSScope> m_next;
85     WriteBarrier<JSGlobalObject> m_globalObject;
86     WriteBarrier<JSObject> m_globalThis;
87 };
88
89 inline JSScope::JSScope(JSGlobalData& globalData, Structure* structure, JSGlobalObject* globalObject, JSObject* globalThis, JSScope* next)
90     : Base(globalData, structure)
91     , m_globalData(&globalData)
92     , m_next(globalData, this, next, WriteBarrier<JSScope>::MayBeNull)
93     , m_globalObject(globalData, this, globalObject)
94     , m_globalThis(globalData, this, globalThis)
95 {
96 }
97
98 class ScopeChainIterator {
99 public:
100     ScopeChainIterator(JSScope* node)
101         : m_node(node)
102     {
103     }
104
105     JSObject* get() const { return JSScope::objectAtScope(m_node); }
106     JSObject* operator->() const { return JSScope::objectAtScope(m_node); }
107
108     ScopeChainIterator& operator++() { m_node = m_node->next(); return *this; }
109
110     // postfix ++ intentionally omitted
111
112     bool operator==(const ScopeChainIterator& other) const { return m_node == other.m_node; }
113     bool operator!=(const ScopeChainIterator& other) const { return m_node != other.m_node; }
114
115 private:
116     JSScope* m_node;
117 };
118
119 inline ScopeChainIterator JSScope::begin()
120 {
121     return ScopeChainIterator(this); 
122 }
123
124 inline ScopeChainIterator JSScope::end()
125
126     return ScopeChainIterator(0); 
127 }
128
129 inline JSScope* JSScope::next()
130
131     return m_next.get();
132 }
133
134 inline JSGlobalObject* JSScope::globalObject()
135
136     return m_globalObject.get();
137 }
138
139 inline JSGlobalData* JSScope::globalData()
140
141     return m_globalData;
142 }
143
144 inline JSObject* JSScope::globalThis()
145
146     return m_globalThis.get();
147 }
148
149 inline void JSScope::setGlobalThis(JSGlobalData& globalData, JSObject* globalThis)
150
151     m_globalThis.set(globalData, this, globalThis);
152 }
153
154 inline Register& Register::operator=(JSScope* scope)
155 {
156     *this = JSValue(scope);
157     return *this;
158 }
159
160 inline JSScope* Register::scope() const
161 {
162     return jsCast<JSScope*>(jsValue());
163 }
164
165 inline JSGlobalData& ExecState::globalData() const
166 {
167     ASSERT(scope()->globalData());
168     return *scope()->globalData();
169 }
170
171 inline JSGlobalObject* ExecState::lexicalGlobalObject() const
172 {
173     return scope()->globalObject();
174 }
175
176 inline JSObject* ExecState::globalThisValue() const
177 {
178     return scope()->globalThis();
179 }
180
181 inline size_t JSScope::offsetOfNext()
182 {
183     return OBJECT_OFFSETOF(JSScope, m_next);
184 }
185
186 } // namespace JSC
187
188 #endif // JSScope_h