Bug 629709 - White line of highlight pixels appears above navigation toolbar if the...
[mozilla-central.git] / js / src / jsscopeinlines.h
blobdd61cbd5a5dcff52f33603d16bc113bbcb4f2822
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
3 * ***** BEGIN LICENSE BLOCK *****
4 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
6 * The contents of this file are subject to the Mozilla Public License Version
7 * 1.1 (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 * http://www.mozilla.org/MPL/
11 * Software distributed under the License is distributed on an "AS IS" basis,
12 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
13 * for the specific language governing rights and limitations under the
14 * License.
16 * The Original Code is Mozilla Communicator client code, released
17 * March 31, 1998.
19 * The Initial Developer of the Original Code is
20 * Netscape Communications Corporation.
21 * Portions created by the Initial Developer are Copyright (C) 1998
22 * the Initial Developer. All Rights Reserved.
24 * Contributor(s):
26 * Alternatively, the contents of this file may be used under the terms of
27 * either of the GNU General Public License Version 2 or later (the "GPL"),
28 * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
29 * in which case the provisions of the GPL or the LGPL are applicable instead
30 * of those above. If you wish to allow use of your version of this file only
31 * under the terms of either the GPL or the LGPL, and not to allow others to
32 * use your version of this file under the terms of the MPL, indicate your
33 * decision by deleting the provisions above and replace them with the notice
34 * and other provisions required by the GPL or the LGPL. If you do not delete
35 * the provisions above, a recipient may use your version of this file under
36 * the terms of any one of the MPL, the GPL or the LGPL.
38 * ***** END LICENSE BLOCK ***** */
40 #ifndef jsscopeinlines_h___
41 #define jsscopeinlines_h___
43 #include <new>
44 #include "jsbool.h"
45 #include "jscntxt.h"
46 #include "jsdbgapi.h"
47 #include "jsfun.h"
48 #include "jsobj.h"
49 #include "jsscope.h"
51 #include "jscntxtinlines.h"
53 inline void
54 js::Shape::freeTable(JSContext *cx)
56 if (table) {
57 cx->destroy(table);
58 table = NULL;
62 inline js::EmptyShape *
63 JSObject::getEmptyShape(JSContext *cx, js::Class *aclasp,
64 /* gc::FinalizeKind */ unsigned kind)
66 JS_ASSERT(kind >= js::gc::FINALIZE_OBJECT0 && kind <= js::gc::FINALIZE_OBJECT_LAST);
67 int i = kind - js::gc::FINALIZE_OBJECT0;
69 if (!emptyShapes) {
70 emptyShapes = (js::EmptyShape**)
71 cx->calloc(sizeof(js::EmptyShape*) * js::gc::JS_FINALIZE_OBJECT_LIMIT);
72 if (!emptyShapes)
73 return NULL;
76 * Always fill in emptyShapes[0], so canProvideEmptyShape works.
77 * Other empty shapes are filled in lazily.
79 emptyShapes[0] = js::EmptyShape::create(cx, aclasp);
80 if (!emptyShapes[0]) {
81 cx->free(emptyShapes);
82 emptyShapes = NULL;
83 return NULL;
87 JS_ASSERT(aclasp == emptyShapes[0]->getClass());
89 if (!emptyShapes[i]) {
90 emptyShapes[i] = js::EmptyShape::create(cx, aclasp);
91 if (!emptyShapes[i])
92 return NULL;
95 return emptyShapes[i];
98 inline bool
99 JSObject::canProvideEmptyShape(js::Class *aclasp)
101 return !emptyShapes || emptyShapes[0]->getClass() == aclasp;
104 inline void
105 JSObject::updateShape(JSContext *cx)
107 JS_ASSERT(isNative());
108 js::LeaveTraceIfGlobalObject(cx, this);
109 if (hasOwnShape())
110 setOwnShape(js_GenerateShape(cx, false));
111 else
112 objShape = lastProp->shape;
115 inline void
116 JSObject::updateFlags(const js::Shape *shape, bool isDefinitelyAtom)
118 jsuint index;
119 if (!isDefinitelyAtom && js_IdIsIndex(shape->id, &index))
120 setIndexed();
122 if (shape->isMethod())
123 setMethodBarrier();
126 inline void
127 JSObject::extend(JSContext *cx, const js::Shape *shape, bool isDefinitelyAtom)
129 setLastProperty(shape);
130 updateFlags(shape, isDefinitelyAtom);
131 updateShape(cx);
134 inline void
135 JSObject::trace(JSTracer *trc)
137 if (!isNative())
138 return;
140 JSContext *cx = trc->context;
141 js::Shape *shape = lastProp;
143 if (IS_GC_MARKING_TRACER(trc) && cx->runtime->gcRegenShapes) {
145 * Either this object has its own shape, which must be regenerated, or
146 * it must have the same shape as lastProp.
148 if (!shape->hasRegenFlag()) {
149 shape->shape = js_RegenerateShapeForGC(cx);
150 shape->setRegenFlag();
153 uint32 newShape = shape->shape;
154 if (hasOwnShape()) {
155 newShape = js_RegenerateShapeForGC(cx);
156 JS_ASSERT(newShape != shape->shape);
158 objShape = newShape;
161 /* Trace our property tree or dictionary ancestor line. */
162 do {
163 shape->trace(trc);
164 } while ((shape = shape->parent) != NULL);
167 namespace js {
169 inline
170 Shape::Shape(jsid id, js::PropertyOp getter, js::PropertyOp setter, uint32 slot, uintN attrs,
171 uintN flags, intN shortid, uint32 shape, uint32 slotSpan)
172 : JSObjectMap(shape, slotSpan),
173 numSearches(0), table(NULL), id(id), rawGetter(getter), rawSetter(setter), slot(slot),
174 attrs(uint8(attrs)), flags(uint8(flags)), shortid(int16(shortid)), parent(NULL)
176 JS_ASSERT_IF(slotSpan != SHAPE_INVALID_SLOT, slotSpan < JSObject::NSLOTS_LIMIT);
177 JS_ASSERT_IF(getter && (attrs & JSPROP_GETTER), getterObj->isCallable());
178 JS_ASSERT_IF(setter && (attrs & JSPROP_SETTER), setterObj->isCallable());
179 kids.setNull();
182 inline
183 Shape::Shape(JSContext *cx, Class *aclasp)
184 : JSObjectMap(js_GenerateShape(cx, false), JSSLOT_FREE(aclasp)), numSearches(0), table(NULL),
185 id(JSID_EMPTY), clasp(aclasp), rawSetter(NULL), slot(SHAPE_INVALID_SLOT), attrs(0),
186 flags(SHARED_EMPTY), shortid(0), parent(NULL)
188 kids.setNull();
191 inline JSDHashNumber
192 Shape::hash() const
194 JSDHashNumber hash = 0;
196 /* Accumulate from least to most random so the low bits are most random. */
197 JS_ASSERT_IF(isMethod(), !rawSetter || rawSetter == js_watch_set);
198 if (rawGetter)
199 hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawGetter);
200 if (rawSetter)
201 hash = JS_ROTATE_LEFT32(hash, 4) ^ jsuword(rawSetter);
202 hash = JS_ROTATE_LEFT32(hash, 4) ^ (flags & PUBLIC_FLAGS);
203 hash = JS_ROTATE_LEFT32(hash, 4) ^ attrs;
204 hash = JS_ROTATE_LEFT32(hash, 4) ^ shortid;
205 hash = JS_ROTATE_LEFT32(hash, 4) ^ slot;
206 hash = JS_ROTATE_LEFT32(hash, 4) ^ JSID_BITS(id);
207 return hash;
210 inline bool
211 Shape::matches(const js::Shape *other) const
213 JS_ASSERT(!JSID_IS_VOID(id));
214 JS_ASSERT(!JSID_IS_VOID(other->id));
215 return id == other->id &&
216 matchesParamsAfterId(other->rawGetter, other->rawSetter, other->slot, other->attrs,
217 other->flags, other->shortid);
220 inline bool
221 Shape::matchesParamsAfterId(js::PropertyOp agetter, js::PropertyOp asetter, uint32 aslot,
222 uintN aattrs, uintN aflags, intN ashortid) const
224 JS_ASSERT(!JSID_IS_VOID(id));
225 return rawGetter == agetter &&
226 rawSetter == asetter &&
227 slot == aslot &&
228 attrs == aattrs &&
229 ((flags ^ aflags) & PUBLIC_FLAGS) == 0 &&
230 shortid == ashortid;
233 inline bool
234 Shape::get(JSContext* cx, JSObject *receiver, JSObject* obj, JSObject *pobj, js::Value* vp) const
236 JS_ASSERT(!JSID_IS_VOID(this->id));
237 JS_ASSERT(!hasDefaultGetter());
239 if (hasGetterValue()) {
240 JS_ASSERT(!isMethod());
241 js::Value fval = getterValue();
242 return js::ExternalGetOrSet(cx, receiver, id, fval, JSACC_READ, 0, 0, vp);
245 if (isMethod()) {
246 vp->setObject(methodObject());
247 return pobj->methodReadBarrier(cx, *this, vp);
251 * |with (it) color;| ends up here, as do XML filter-expressions.
252 * Avoid exposing the With object to native getters.
254 if (obj->getClass() == &js_WithClass)
255 obj = js_UnwrapWithObject(cx, obj);
256 return js::CallJSPropertyOp(cx, getterOp(), obj, SHAPE_USERID(this), vp);
259 inline bool
260 Shape::set(JSContext* cx, JSObject* obj, js::Value* vp) const
262 JS_ASSERT_IF(hasDefaultSetter(), hasGetterValue());
264 if (attrs & JSPROP_SETTER) {
265 js::Value fval = setterValue();
266 return js::ExternalGetOrSet(cx, obj, id, fval, JSACC_WRITE, 1, vp, vp);
269 if (attrs & JSPROP_GETTER)
270 return js_ReportGetterOnlyAssignment(cx);
272 /* See the comment in js::Shape::get as to why we check for With. */
273 if (obj->getClass() == &js_WithClass)
274 obj = js_UnwrapWithObject(cx, obj);
275 return js::CallJSPropertyOpSetter(cx, setterOp(), obj, SHAPE_USERID(this), vp);
278 inline
279 EmptyShape::EmptyShape(JSContext *cx, js::Class *aclasp)
280 : js::Shape(cx, aclasp)
282 #ifdef DEBUG
283 if (cx->runtime->meterEmptyShapes())
284 cx->runtime->emptyShapes.put(this);
285 #endif
288 } /* namespace js */
290 #endif /* jsscopeinlines_h___ */