source: webkit/trunk/JavaScriptCore/kjs/nodes.cpp@ 10076

Last change on this file since 10076 was 10076, checked in by mjs, 20 years ago

JavaScriptCore:

Reviewed by Darin.

Change over to the new PropertySlot mechanism for property
lookup. This allows the elimination of hasOwnProperty
methods. Also did some of the performance tuning enabled by this
(but not yet all the possible improvements for function calls,
assignment, ++, and so forth). And also much code cleanup.

Net result is about a 2% speedup on the JS iBench.

Also redid Geoff's fix for the chrashing applet by avoiding a NULL
prototype in the bindings code and using the default of Null()
instead.

  • JavaScriptCore.xcodeproj/project.pbxproj:
  • bindings/objc/objc_runtime.h:
  • bindings/objc/objc_runtime.mm: (ObjcFallbackObjectImp::ObjcFallbackObjectImp): (ObjcFallbackObjectImp::getOwnPropertySlot):
  • bindings/runtime_array.cpp: (RuntimeArrayImp::lengthGetter): (RuntimeArrayImp::indexGetter): (RuntimeArrayImp::getOwnPropertySlot):
  • bindings/runtime_array.h:
  • bindings/runtime_method.cpp: (RuntimeMethodImp::lengthGetter): (RuntimeMethodImp::getOwnPropertySlot):
  • bindings/runtime_method.h:
  • bindings/runtime_object.cpp: (RuntimeObjectImp::RuntimeObjectImp): (RuntimeObjectImp::fallbackObjectGetter): (RuntimeObjectImp::fieldGetter): (RuntimeObjectImp::methodGetter): (RuntimeObjectImp::getOwnPropertySlot):
  • bindings/runtime_object.h:
  • bindings/runtime_root.h:
  • kjs/array_instance.h:
  • kjs/array_object.cpp: (ArrayInstanceImp::lengthGetter): (ArrayInstanceImp::getOwnPropertySlot): (ArrayPrototypeImp::getOwnPropertySlot):
  • kjs/array_object.h:
  • kjs/date_object.cpp: (DatePrototypeImp::getOwnPropertySlot):
  • kjs/date_object.h:
  • kjs/function.cpp: (KJS::FunctionImp::argumentsGetter): (KJS::FunctionImp::lengthGetter): (KJS::FunctionImp::getOwnPropertySlot): (KJS::FunctionImp::put): (KJS::FunctionImp::deleteProperty): (KJS::ArgumentsImp::mappedIndexGetter): (KJS::ArgumentsImp::getOwnPropertySlot): (KJS::ActivationImp::argumentsGetter): (KJS::ActivationImp::getArgumentsGetter): (KJS::ActivationImp::getOwnPropertySlot): (KJS::ActivationImp::deleteProperty):
  • kjs/function.h:
  • kjs/internal.cpp: (InterpreterImp::InterpreterImp): (InterpreterImp::initGlobalObject): (InterpreterImp::~InterpreterImp): (InterpreterImp::evaluate):
  • kjs/internal.h: (KJS::InterpreterImp::globalExec):
  • kjs/interpreter.cpp: (Interpreter::Interpreter): (Interpreter::createLanguageInstanceForValue):
  • kjs/interpreter.h: (KJS::Interpreter::argumentsIdentifier): (KJS::Interpreter::specialPrototypeIdentifier):
  • kjs/lookup.h: (KJS::staticFunctionGetter): (KJS::staticValueGetter): (KJS::getStaticPropertySlot): (KJS::getStaticFunctionSlot): (KJS::getStaticValueSlot):
  • kjs/math_object.cpp: (MathObjectImp::getOwnPropertySlot):
  • kjs/math_object.h:
  • kjs/nodes.cpp: (ResolveNode::evaluate): (ResolveNode::evaluateReference): (AccessorNode1::evaluate): (AccessorNode2::evaluate):
  • kjs/number_object.cpp: (NumberObjectImp::getOwnPropertySlot):
  • kjs/number_object.h:
  • kjs/object.cpp: (KJS::ObjectImp::get): (KJS::ObjectImp::getProperty): (KJS::ObjectImp::getPropertySlot): (KJS::ObjectImp::getOwnPropertySlot): (KJS::ObjectImp::put): (KJS::ObjectImp::hasProperty): (KJS::ObjectImp::hasOwnProperty):
  • kjs/object.h: (KJS::ObjectImp::getDirectLocation): (KJS::ObjectImp::getPropertySlot): (KJS::ObjectImp::getOwnPropertySlot):
  • kjs/object_wrapper.h: Added. (KJS::): (KJS::Object::Object): (KJS::Object::operator ObjectImp *):
  • kjs/property_map.cpp: (KJS::PropertyMap::getLocation):
  • kjs/property_map.h:
  • kjs/property_slot.cpp: Added. (KJS::PropertySlot::undefinedGetter):
  • kjs/property_slot.h: Added. (KJS::PropertySlot::isSet): (KJS::PropertySlot::getValue): (KJS::PropertySlot::setValueSlot): (KJS::PropertySlot::setStaticEntry): (KJS::PropertySlot::setCustom): (KJS::PropertySlot::setCustomIndex): (KJS::PropertySlot::setUndefined): (KJS::PropertySlot::slotBase): (KJS::PropertySlot::staticEntry): (KJS::PropertySlot::index): (KJS::PropertySlot::):
  • kjs/protect.h:
  • kjs/protected_object.h: Added. (KJS::ProtectedObject::ProtectedObject): (KJS::ProtectedObject::~ProtectedObject): (KJS::ProtectedObject::operator=): (KJS::ProtectedReference::ProtectedReference): (KJS::ProtectedReference::~ProtectedReference): (KJS::ProtectedReference::operator=):
  • kjs/reference.h:
  • kjs/reference_list.cpp:
  • kjs/regexp_object.cpp: (RegExpObjectImp::backrefGetter): (RegExpObjectImp::getOwnPropertySlot):
  • kjs/regexp_object.h:
  • kjs/string_object.cpp: (StringInstanceImp::lengthGetter): (StringInstanceImp::indexGetter): (StringInstanceImp::getOwnPropertySlot): (StringPrototypeImp::getOwnPropertySlot):
  • kjs/string_object.h:

WebCore:

Reviewed by Darin.

Change over to the new PropertySlot mechanism for property
lookup. This allows the elimination of hasOwnProperty methods. I
also did a bunch of code cleanup and regularization of the various
property lookup methods.

Test cases added: Added a test case for a bug I found along the way.

  • layout-tests/fast/js/string-index-overflow.html:
  • layout-tests/fast/js/string-index-overflow-expected.txt:
  • khtml/ecma/kjs_binding.cpp: (KJS::ScriptInterpreter::createLanguageInstanceForValue):
  • khtml/ecma/kjs_binding.h:
  • khtml/ecma/kjs_css.cpp: (KJS::DOMCSSStyleDeclaration::indexGetter): (KJS::DOMCSSStyleDeclaration::cssPropertyGetter): (KJS::DOMCSSStyleDeclaration::getOwnPropertySlot): (KJS::DOMCSSStyleDeclaration::getValueProperty): (KJS::DOMStyleSheet::getOwnPropertySlot): (KJS::DOMStyleSheetList::getValueProperty): (KJS::DOMStyleSheetList::indexGetter): (KJS::DOMStyleSheetList::nameGetter): (KJS::DOMStyleSheetList::getOwnPropertySlot): (KJS::DOMMediaList::getValueProperty): (KJS::DOMMediaList::indexGetter): (KJS::DOMMediaList::getOwnPropertySlot): (KJS::DOMCSSStyleSheet::getValueProperty): (KJS::DOMCSSStyleSheet::getOwnPropertySlot): (KJS::DOMCSSRuleList::getValueProperty): (KJS::DOMCSSRuleList::indexGetter): (KJS::DOMCSSRuleList::getOwnPropertySlot): (KJS::DOMCSSRule::getOwnPropertySlot): (KJS::CSSRuleConstructor::getOwnPropertySlot): (KJS::DOMCSSValue::getValueProperty): (KJS::DOMCSSValue::getOwnPropertySlot): (KJS::CSSValueConstructor::getOwnPropertySlot): (KJS::DOMCSSPrimitiveValue::getValueProperty): (KJS::DOMCSSPrimitiveValue::getOwnPropertySlot): (KJS::CSSPrimitiveValueConstructor::getOwnPropertySlot): (KJS::DOMCSSValueList::getValueProperty): (KJS::DOMCSSValueList::indexGetter): (KJS::DOMCSSValueList::getOwnPropertySlot): (KJS::DOMRGBColor::getOwnPropertySlot): (KJS::DOMRect::getOwnPropertySlot): (KJS::DOMCounter::getOwnPropertySlot):
  • khtml/ecma/kjs_css.h: (KJS::DOMCSSStyleDeclaration::): (KJS::DOMCSSStyleSheet::): (KJS::DOMCSSRule::): (KJS::DOMCSSValueList::):
  • khtml/ecma/kjs_dom.cpp: (KJS::DOMNode::getOwnPropertySlot): (KJS::): (KJS::DOMNodeList::getValueProperty): (KJS::DOMNodeList::indexGetter): (KJS::DOMNodeList::nameGetter): (KJS::DOMNodeList::getOwnPropertySlot): (KJS::DOMNodeList::call): (KJS::DOMAttr::getOwnPropertySlot): (KJS::DOMDocument::getOwnPropertySlot): (KJS::DOMElement::getValueProperty): (KJS::DOMElement::attributeGetter): (KJS::DOMElement::getOwnPropertySlot): (KJS::DOMDocumentType::getOwnPropertySlot): (KJS::DOMNamedNodeMap::lengthGetter): (KJS::DOMNamedNodeMap::indexGetter): (KJS::DOMNamedNodeMap::getOwnPropertySlot): (KJS::DOMProcessingInstruction::getOwnPropertySlot): (KJS::DOMNotation::getOwnPropertySlot): (KJS::DOMEntity::getOwnPropertySlot): (KJS::NodeConstructor::getOwnPropertySlot): (KJS::DOMExceptionConstructor::getOwnPropertySlot): (KJS::DOMNamedNodesCollection::lengthGetter): (KJS::DOMNamedNodesCollection::indexGetter): (KJS::DOMNamedNodesCollection::getOwnPropertySlot): (KJS::DOMCharacterData::getOwnPropertySlot):
  • khtml/ecma/kjs_dom.h:
  • khtml/ecma/kjs_events.cpp: (KJS::EventConstructor::getOwnPropertySlot): (KJS::DOMEvent::getOwnPropertySlot): (KJS::EventExceptionConstructor::getOwnPropertySlot): (KJS::DOMUIEvent::getOwnPropertySlot): (KJS::DOMMouseEvent::getOwnPropertySlot): (KJS::DOMKeyboardEvent::getOwnPropertySlot): (KJS::MutationEventConstructor::getOwnPropertySlot): (KJS::DOMMutationEvent::getOwnPropertySlot): (KJS::DOMWheelEvent::getOwnPropertySlot): (KJS::Clipboard::getOwnPropertySlot):
  • khtml/ecma/kjs_events.h:
  • khtml/ecma/kjs_html.cpp: (KJS::HTMLDocument::namedItemGetter): (KJS::HTMLDocument::getValueProperty): (KJS::HTMLDocument::getOwnPropertySlot): (KJS::HTMLElement::formIndexGetter): (KJS::HTMLElement::formNameGetter): (KJS::HTMLElement::selectIndexGetter): (KJS::HTMLElement::framesetNameGetter): (KJS::HTMLElement::frameWindowPropertyGetter): (KJS::HTMLElement::runtimeObjectGetter): (KJS::HTMLElement::runtimeObjectPropertyGetter): (KJS::HTMLElement::getOwnPropertySlot): (KJS::HTMLCollection::lengthGetter): (KJS::HTMLCollection::indexGetter): (KJS::HTMLCollection::nameGetter): (KJS::HTMLCollection::getOwnPropertySlot): (KJS::HTMLSelectCollection::selectedIndexGetter): (KJS::HTMLSelectCollection::getOwnPropertySlot): (KJS::Image::getOwnPropertySlot): (KJS::Context2D::getOwnPropertySlot): (KJS::Gradient::getOwnPropertySlot): (KJS::ImagePattern::getOwnPropertySlot):
  • khtml/ecma/kjs_html.h: (KJS::HTMLCollection::toBoolean):
  • khtml/ecma/kjs_navigator.cpp: (KJS::Plugins::): (KJS::MimeTypes::): (KJS::Plugin::): (KJS::MimeType::): (KJS::): (KJS::Navigator::getOwnPropertySlot): (KJS::Plugins::getValueProperty): (KJS::Plugins::indexGetter): (KJS::Plugins::nameGetter): (KJS::Plugins::getOwnPropertySlot): (KJS::MimeTypes::getValueProperty): (KJS::MimeTypes::indexGetter): (KJS::MimeTypes::nameGetter): (KJS::MimeTypes::getOwnPropertySlot): (KJS::Plugin::getValueProperty): (KJS::Plugin::indexGetter): (KJS::Plugin::nameGetter): (KJS::Plugin::getOwnPropertySlot): (KJS::MimeType::getValueProperty): (KJS::MimeType::getOwnPropertySlot):
  • khtml/ecma/kjs_navigator.h:
  • khtml/ecma/kjs_range.cpp: (KJS::DOMRange::getOwnPropertySlot): (KJS::RangeConstructor::getOwnPropertySlot):
  • khtml/ecma/kjs_range.h:
  • khtml/ecma/kjs_traversal.cpp: (KJS::DOMNodeIterator::getOwnPropertySlot): (KJS::NodeFilterConstructor::getOwnPropertySlot): (KJS::DOMTreeWalker::getOwnPropertySlot):
  • khtml/ecma/kjs_traversal.h:
  • khtml/ecma/kjs_views.cpp: (KJS::DOMAbstractView::~DOMAbstractView): (KJS::DOMAbstractView::getValueProperty): (KJS::DOMAbstractView::getOwnPropertySlot):
  • khtml/ecma/kjs_views.h:
  • khtml/ecma/kjs_window.cpp: (KJS::FrameArray::): (KJS::FrameArray::classInfo): (KJS::Screen::getOwnPropertySlot): (KJS::Window::getValueProperty): (KJS::Window::childFrameGetter): (KJS::Window::namedFrameGetter): (KJS::Window::indexGetter): (KJS::Window::namedItemGetter): (KJS::Window::getOwnPropertySlot): (KJS::): (KJS::FrameArray::getValueProperty): (KJS::FrameArray::indexGetter): (KJS::FrameArray::nameGetter): (KJS::FrameArray::getOwnPropertySlot): (KJS::Location::getValueProperty): (KJS::Location::getOwnPropertySlot): (KJS::Selection::getValueProperty): (KJS::Selection::getOwnPropertySlot): (KJS::BarInfo::getValueProperty): (KJS::BarInfo::getOwnPropertySlot): (KJS::History::getOwnPropertySlot):
  • khtml/ecma/kjs_window.h:
  • khtml/ecma/xmlhttprequest.cpp: (KJS::XMLHttpRequest::getOwnPropertySlot):
  • khtml/ecma/xmlhttprequest.h:
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 62.6 KB
Line 
1// -*- c-basic-offset: 2 -*-
2/*
3 * This file is part of the KDE libraries
4 * Copyright (C) 1999-2002 Harri Porten ([email protected])
5 * Copyright (C) 2001 Peter Kelly ([email protected])
6 * Copyright (C) 2003 Apple Computer, Inc.
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25#include "nodes.h"
26
27//#include <iostream>
28#include <math.h>
29#include <assert.h>
30#ifdef KJS_DEBUG_MEM
31#include <stdio.h>
32#include <typeinfo>
33#endif
34
35#include "collector.h"
36#include "context.h"
37#include "debugger.h"
38#include "function_object.h"
39#include "internal.h"
40#include "value.h"
41#include "object.h"
42#include "types.h"
43#include "interpreter.h"
44#include "lexer.h"
45#include "operations.h"
46#include "ustring.h"
47
48using namespace KJS;
49
50#define KJS_BREAKPOINT \
51 if (Debugger::debuggersPresent > 0 && !hitStatement(exec)) \
52 return Completion(Normal);
53
54#define KJS_ABORTPOINT \
55 if (Debugger::debuggersPresent > 0 && \
56 exec->dynamicInterpreter()->imp()->debugger() && \
57 exec->dynamicInterpreter()->imp()->debugger()->imp()->aborted()) \
58 return Completion(Normal);
59
60#define KJS_CHECKEXCEPTION \
61 if (exec->hadException()) { \
62 setExceptionDetailsIfNeeded(exec); \
63 return Completion(Throw, exec->exception()); \
64 } \
65 if (Collector::outOfMemory()) \
66 return Completion(Throw, Error::create(exec,GeneralError,"Out of memory"));
67
68#define KJS_CHECKEXCEPTIONVALUE \
69 if (exec->hadException()) { \
70 setExceptionDetailsIfNeeded(exec); \
71 return exec->exception(); \
72 } \
73 if (Collector::outOfMemory()) \
74 return Undefined(); // will be picked up by KJS_CHECKEXCEPTION
75
76#define KJS_CHECKEXCEPTIONREFERENCE \
77 if (exec->hadException()) { \
78 setExceptionDetailsIfNeeded(exec); \
79 return Reference::makeValueReference(Undefined()); \
80 } \
81 if (Collector::outOfMemory()) \
82 return Reference::makeValueReference(Undefined()); // will be picked up by KJS_CHECKEXCEPTION
83
84#define KJS_CHECKEXCEPTIONLIST \
85 if (exec->hadException()) { \
86 setExceptionDetailsIfNeeded(exec); \
87 return List(); \
88 } \
89 if (Collector::outOfMemory()) \
90 return List(); // will be picked up by KJS_CHECKEXCEPTION
91
92#ifdef KJS_DEBUG_MEM
93std::list<Node *> * Node::s_nodes = 0L;
94#endif
95
96// ------------------------------ Node -----------------------------------------
97
98Node::Node()
99{
100 line = Lexer::curr()->lineNo();
101 sourceURL = Lexer::curr()->sourceURL();
102 refcount = 0;
103#ifdef KJS_DEBUG_MEM
104 if (!s_nodes)
105 s_nodes = new std::list<Node *>;
106 s_nodes->push_back(this);
107#endif
108}
109
110Node::~Node()
111{
112#ifdef KJS_DEBUG_MEM
113 s_nodes->remove( this );
114#endif
115}
116
117Reference Node::evaluateReference(ExecState *exec)
118{
119 Value v = evaluate(exec);
120 KJS_CHECKEXCEPTIONREFERENCE
121 return Reference::makeValueReference(v);
122}
123
124#ifdef KJS_DEBUG_MEM
125void Node::finalCheck()
126{
127 fprintf( stderr, "Node::finalCheck(): list count : %d\n", (int)s_nodes.size() );
128 std::list<Node *>::iterator it = s_nodes->begin();
129 for ( uint i = 0; it != s_nodes->end() ; ++it, ++i )
130 fprintf( stderr, "[%d] Still having node %p (%s) (refcount %d)\n", i, (void*)*it, typeid( **it ).name(), (*it)->refcount );
131 delete s_nodes;
132 s_nodes = 0L;
133}
134#endif
135
136Value Node::throwError(ExecState *exec, ErrorType e, const char *msg)
137{
138 Object err = Error::create(exec, e, msg, lineNo(), sourceId(), &sourceURL);
139 exec->setException(err);
140 return err;
141}
142
143Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, Value v, Node *expr)
144{
145 char *vStr = strdup(v.toString(exec).ascii());
146 char *exprStr = strdup(expr->toString().ascii());
147
148 int length = strlen(msg) - 4 /* two %s */ + strlen(vStr) + strlen(exprStr) + 1 /* null terminator */;
149 char *str = new char[length];
150 sprintf(str, msg, vStr, exprStr);
151 free(vStr);
152 free(exprStr);
153
154 Value result = throwError(exec, e, str);
155 delete [] str;
156
157 return result;
158}
159
160
161Value Node::throwError(ExecState *exec, ErrorType e, const char *msg, Identifier label)
162{
163 const char *l = label.ascii();
164 int length = strlen(msg) - 2 /* %s */ + strlen(l) + 1 /* null terminator */;
165 char *message = new char[length];
166 sprintf(message, msg, l);
167
168 Value result = throwError(exec, e, message);
169 delete [] message;
170
171 return result;
172}
173
174void Node::setExceptionDetailsIfNeeded(ExecState *exec)
175{
176 if (exec->hadException()) {
177 Object exception = exec->exception().toObject(exec);
178 if (!exception.hasProperty(exec, "line") &&
179 !exception.hasProperty(exec, "sourceURL")) {
180 exception.put(exec, "line", Number(line));
181 exception.put(exec, "sourceURL", String(sourceURL));
182 }
183 }
184}
185
186
187// ------------------------------ StatementNode --------------------------------
188StatementNode::StatementNode() : l0(-1), l1(-1), sid(-1), breakPoint(false)
189{
190}
191
192void StatementNode::setLoc(int line0, int line1, int sourceId)
193{
194 l0 = line0;
195 l1 = line1;
196 sid = sourceId;
197}
198
199// return true if the debugger wants us to stop at this point
200bool StatementNode::hitStatement(ExecState *exec)
201{
202 Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
203 if (dbg)
204 return dbg->atStatement(exec,sid,l0,l1);
205 else
206 return true; // continue
207}
208
209// return true if the debugger wants us to stop at this point
210bool StatementNode::abortStatement(ExecState *exec)
211{
212 Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
213 if (dbg)
214 return dbg->imp()->aborted();
215 else
216 return false;
217}
218
219void StatementNode::processFuncDecl(ExecState *exec)
220{
221}
222
223// ------------------------------ NullNode -------------------------------------
224
225Value NullNode::evaluate(ExecState */*exec*/)
226{
227 return Null();
228}
229
230// ------------------------------ BooleanNode ----------------------------------
231
232Value BooleanNode::evaluate(ExecState */*exec*/)
233{
234 return Value(value);
235}
236
237// ------------------------------ NumberNode -----------------------------------
238
239Value NumberNode::evaluate(ExecState */*exec*/)
240{
241 return Value(value);
242}
243
244// ------------------------------ StringNode -----------------------------------
245
246Value StringNode::evaluate(ExecState */*exec*/)
247{
248 return value;
249}
250
251// ------------------------------ RegExpNode -----------------------------------
252
253Value RegExpNode::evaluate(ExecState *exec)
254{
255 List list;
256 String p(pattern);
257 String f(flags);
258 list.append(p);
259 list.append(f);
260
261 Object reg = exec->lexicalInterpreter()->imp()->builtinRegExp();
262 return reg.construct(exec,list);
263}
264
265// ------------------------------ ThisNode -------------------------------------
266
267// ECMA 11.1.1
268Value ThisNode::evaluate(ExecState *exec)
269{
270 return exec->context().imp()->thisValue();
271}
272
273// ------------------------------ ResolveNode ----------------------------------
274
275// ECMA 11.1.2 & 10.1.4
276Value ResolveNode::evaluate(ExecState *exec)
277{
278 ScopeChain chain = exec->context().imp()->scopeChain();
279
280 assert(!chain.isEmpty());
281
282 PropertySlot slot;
283 do {
284 ObjectImp *o = chain.top();
285 if (o->getPropertySlot(exec, ident, slot))
286 return slot.getValue(exec, ident);
287
288 chain.pop();
289 } while (!chain.isEmpty());
290
291 return Reference(Null(), ident).getValue(exec);
292}
293
294Reference ResolveNode::evaluateReference(ExecState *exec)
295{
296 ScopeChain chain = exec->context().imp()->scopeChain();
297
298 assert(!chain.isEmpty());
299
300 PropertySlot slot;
301 do {
302 ObjectImp *o = chain.top();
303 if (o->getPropertySlot(exec, ident, slot))
304 return Reference(o, ident);
305
306 chain.pop();
307 } while (!chain.isEmpty());
308
309 return Reference(Null(), ident);
310}
311
312
313// ------------------------------ GroupNode ------------------------------------
314
315void GroupNode::ref()
316{
317 Node::ref();
318 if ( group )
319 group->ref();
320}
321
322bool GroupNode::deref()
323{
324 if ( group && group->deref() )
325 delete group;
326 return Node::deref();
327}
328
329// ECMA 11.1.6
330Value GroupNode::evaluate(ExecState *exec)
331{
332 return group->evaluate(exec);
333}
334
335Reference GroupNode::evaluateReference(ExecState *exec)
336{
337 return group->evaluateReference(exec);
338}
339
340// ------------------------------ ElementNode ----------------------------------
341
342void ElementNode::ref()
343{
344 for (ElementNode *n = this; n; n = n->list) {
345 n->Node::ref();
346 if (n->node)
347 n->node->ref();
348 }
349}
350
351bool ElementNode::deref()
352{
353 ElementNode *next;
354 for (ElementNode *n = this; n; n = next) {
355 next = n->list;
356 if (n->node && n->node->deref())
357 delete n->node;
358 if (n != this && n->Node::deref())
359 delete n;
360 }
361 return Node::deref();
362}
363
364// ECMA 11.1.4
365Value ElementNode::evaluate(ExecState *exec)
366{
367 Object array = exec->lexicalInterpreter()->builtinArray().construct(exec, List::empty());
368 int length = 0;
369 for (ElementNode *n = this; n; n = n->list) {
370 Value val = n->node->evaluate(exec);
371 KJS_CHECKEXCEPTIONVALUE
372 length += n->elision;
373 array.put(exec, length++, val);
374 }
375 return array;
376}
377
378// ------------------------------ ArrayNode ------------------------------------
379
380void ArrayNode::ref()
381{
382 Node::ref();
383 if ( element )
384 element->ref();
385}
386
387bool ArrayNode::deref()
388{
389 if ( element && element->deref() )
390 delete element;
391 return Node::deref();
392}
393
394// ECMA 11.1.4
395Value ArrayNode::evaluate(ExecState *exec)
396{
397 Object array;
398 int length;
399
400 if (element) {
401 array = Object(static_cast<ObjectImp*>(element->evaluate(exec).imp()));
402 KJS_CHECKEXCEPTIONVALUE
403 length = opt ? array.get(exec,lengthPropertyName).toInt32(exec) : 0;
404 } else {
405 Value newArr = exec->lexicalInterpreter()->builtinArray().construct(exec,List::empty());
406 array = Object(static_cast<ObjectImp*>(newArr.imp()));
407 length = 0;
408 }
409
410 if (opt)
411 array.put(exec,lengthPropertyName, Value(elision + length), DontEnum | DontDelete);
412
413 return array;
414}
415
416// ------------------------------ ObjectLiteralNode ----------------------------
417
418void ObjectLiteralNode::ref()
419{
420 Node::ref();
421 if ( list )
422 list->ref();
423}
424
425bool ObjectLiteralNode::deref()
426{
427 if ( list && list->deref() )
428 delete list;
429 return Node::deref();
430}
431
432// ECMA 11.1.5
433Value ObjectLiteralNode::evaluate(ExecState *exec)
434{
435 if (list)
436 return list->evaluate(exec);
437
438 return exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty());
439}
440
441// ------------------------------ PropertyValueNode ----------------------------
442
443void PropertyValueNode::ref()
444{
445 for (PropertyValueNode *n = this; n; n = n->list) {
446 n->Node::ref();
447 if (n->name)
448 n->name->ref();
449 if (n->assign)
450 n->assign->ref();
451 }
452}
453
454bool PropertyValueNode::deref()
455{
456 PropertyValueNode *next;
457 for (PropertyValueNode *n = this; n; n = next) {
458 next = n->list;
459 if ( n->name && n->name->deref() )
460 delete n->name;
461 if ( n->assign && n->assign->deref() )
462 delete n->assign;
463 if (n != this && n->Node::deref() )
464 delete n;
465 }
466 return Node::deref();
467}
468
469// ECMA 11.1.5
470Value PropertyValueNode::evaluate(ExecState *exec)
471{
472 Object obj = exec->lexicalInterpreter()->builtinObject().construct(exec, List::empty());
473
474 for (PropertyValueNode *p = this; p; p = p->list) {
475 Value n = p->name->evaluate(exec);
476 KJS_CHECKEXCEPTIONVALUE
477 Value v = p->assign->evaluate(exec);
478 KJS_CHECKEXCEPTIONVALUE
479
480 obj.put(exec, Identifier(n.toString(exec)), v);
481 }
482
483 return obj;
484}
485
486// ------------------------------ PropertyNode ---------------------------------
487
488// ECMA 11.1.5
489Value PropertyNode::evaluate(ExecState */*exec*/)
490{
491 Value s;
492
493 if (str.isNull()) {
494 s = String(UString::from(numeric));
495 } else {
496 s = String(str.ustring());
497 }
498
499 return s;
500}
501
502// ------------------------------ AccessorNode1 --------------------------------
503
504void AccessorNode1::ref()
505{
506 Node::ref();
507 if ( expr1 )
508 expr1->ref();
509 if ( expr2 )
510 expr2->ref();
511}
512
513bool AccessorNode1::deref()
514{
515 if ( expr1 && expr1->deref() )
516 delete expr1;
517 if ( expr2 && expr2->deref() )
518 delete expr2;
519 return Node::deref();
520}
521
522// ECMA 11.2.1a
523Value AccessorNode1::evaluate(ExecState *exec)
524{
525 Value v1 = expr1->evaluate(exec);
526 KJS_CHECKEXCEPTIONVALUE
527 Value v2 = expr2->evaluate(exec);
528 KJS_CHECKEXCEPTIONVALUE
529 Object o = v1.toObject(exec);
530 unsigned i;
531 if (v2.toUInt32(i))
532 return o.get(exec, i);
533
534 String s = v2.toString(exec);
535 return o.get(exec, Identifier(s.value()));
536}
537
538Reference AccessorNode1::evaluateReference(ExecState *exec)
539{
540 Value v1 = expr1->evaluate(exec);
541 KJS_CHECKEXCEPTIONREFERENCE
542 Value v2 = expr2->evaluate(exec);
543 KJS_CHECKEXCEPTIONREFERENCE
544 Object o = v1.toObject(exec);
545 unsigned i;
546 if (v2.toUInt32(i))
547 return Reference(o, i);
548 String s = v2.toString(exec);
549 return Reference(o, Identifier(s.value()));
550}
551
552
553// ------------------------------ AccessorNode2 --------------------------------
554
555void AccessorNode2::ref()
556{
557 Node::ref();
558 if ( expr )
559 expr->ref();
560}
561
562bool AccessorNode2::deref()
563{
564 if ( expr && expr->deref() )
565 delete expr;
566 return Node::deref();
567}
568
569// ECMA 11.2.1b
570Value AccessorNode2::evaluate(ExecState *exec)
571{
572 Value v = expr->evaluate(exec);
573 KJS_CHECKEXCEPTIONVALUE
574 Object o = v.toObject(exec);
575 return o.get(exec, ident);
576
577}
578
579Reference AccessorNode2::evaluateReference(ExecState *exec)
580{
581 Value v = expr->evaluate(exec);
582 KJS_CHECKEXCEPTIONREFERENCE
583 Object o = v.toObject(exec);
584 return Reference(o, ident);
585}
586
587// ------------------------------ ArgumentListNode -----------------------------
588
589void ArgumentListNode::ref()
590{
591 for (ArgumentListNode *n = this; n; n = n->list) {
592 n->Node::ref();
593 if (n->expr)
594 n->expr->ref();
595 }
596}
597
598bool ArgumentListNode::deref()
599{
600 ArgumentListNode *next;
601 for (ArgumentListNode *n = this; n; n = next) {
602 next = n->list;
603 if (n->expr && n->expr->deref())
604 delete n->expr;
605 if (n != this && n->Node::deref())
606 delete n;
607 }
608 return Node::deref();
609}
610
611Value ArgumentListNode::evaluate(ExecState */*exec*/)
612{
613 assert(0);
614 return Value(); // dummy, see evaluateList()
615}
616
617// ECMA 11.2.4
618List ArgumentListNode::evaluateList(ExecState *exec)
619{
620 List l;
621
622 for (ArgumentListNode *n = this; n; n = n->list) {
623 Value v = n->expr->evaluate(exec);
624 KJS_CHECKEXCEPTIONLIST
625 l.append(v);
626 }
627
628 return l;
629}
630
631// ------------------------------ ArgumentsNode --------------------------------
632
633void ArgumentsNode::ref()
634{
635 Node::ref();
636 if ( list )
637 list->ref();
638}
639
640bool ArgumentsNode::deref()
641{
642 if ( list && list->deref() )
643 delete list;
644 return Node::deref();
645}
646
647Value ArgumentsNode::evaluate(ExecState */*exec*/)
648{
649 assert(0);
650 return Value(); // dummy, see evaluateList()
651}
652
653// ECMA 11.2.4
654List ArgumentsNode::evaluateList(ExecState *exec)
655{
656 if (!list)
657 return List();
658
659 return list->evaluateList(exec);
660}
661
662// ------------------------------ NewExprNode ----------------------------------
663
664// ECMA 11.2.2
665
666void NewExprNode::ref()
667{
668 Node::ref();
669 if ( expr )
670 expr->ref();
671 if ( args )
672 args->ref();
673}
674
675bool NewExprNode::deref()
676{
677 if ( expr && expr->deref() )
678 delete expr;
679 if ( args && args->deref() )
680 delete args;
681 return Node::deref();
682}
683
684Value NewExprNode::evaluate(ExecState *exec)
685{
686 Value v = expr->evaluate(exec);
687 KJS_CHECKEXCEPTIONVALUE
688
689 List argList;
690 if (args) {
691 argList = args->evaluateList(exec);
692 KJS_CHECKEXCEPTIONVALUE
693 }
694
695 if (v.type() != ObjectType) {
696 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, expr);
697 }
698
699 Object constr = Object(static_cast<ObjectImp*>(v.imp()));
700 if (!constr.implementsConstruct()) {
701 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr);
702 }
703
704 Value res = constr.construct(exec,argList);
705
706 return res;
707}
708
709// ------------------------------ FunctionCallNode -----------------------------
710
711void FunctionCallNode::ref()
712{
713 Node::ref();
714 if ( expr )
715 expr->ref();
716 if ( args )
717 args->ref();
718}
719
720bool FunctionCallNode::deref()
721{
722 if ( expr && expr->deref() )
723 delete expr;
724 if ( args && args->deref() )
725 delete args;
726 return Node::deref();
727}
728
729// ECMA 11.2.3
730Value FunctionCallNode::evaluate(ExecState *exec)
731{
732 Reference ref = expr->evaluateReference(exec);
733 KJS_CHECKEXCEPTIONVALUE
734
735 List argList = args->evaluateList(exec);
736 KJS_CHECKEXCEPTIONVALUE
737
738 Value v = ref.getValue(exec);
739 KJS_CHECKEXCEPTIONVALUE
740
741 if (v.type() != ObjectType) {
742 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, expr);
743 }
744
745 ObjectImp *func = static_cast<ObjectImp*>(v.imp());
746
747 if (!func->implementsCall()) {
748 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, expr);
749 }
750
751 ObjectImp *thisObjImp = 0;
752 ValueImp *thisValImp = ref.baseIfMutable();
753 if (thisValImp && thisValImp->type() == ObjectType && !static_cast<ObjectImp *>(thisValImp)->inherits(&ActivationImp::info))
754 thisObjImp = static_cast<ObjectImp *>(thisValImp);
755
756 if (!thisObjImp) {
757 // ECMA 11.2.3 says that in this situation the this value should be null.
758 // However, section 10.2.3 says that in the case where the value provided
759 // by the caller is null, the global object should be used. It also says
760 // that the section does not apply to interal functions, but for simplicity
761 // of implementation we use the global object anyway here. This guarantees
762 // that in host objects you always get a valid object for this.
763 thisObjImp = exec->dynamicInterpreter()->globalObject().imp();
764 }
765
766 Object thisObj(thisObjImp);
767 return func->call(exec, thisObj, argList);
768}
769
770// ------------------------------ PostfixNode ----------------------------------
771
772void PostfixNode::ref()
773{
774 Node::ref();
775 if ( expr )
776 expr->ref();
777}
778
779bool PostfixNode::deref()
780{
781 if ( expr && expr->deref() )
782 delete expr;
783 return Node::deref();
784}
785
786// ECMA 11.3
787Value PostfixNode::evaluate(ExecState *exec)
788{
789 Reference ref = expr->evaluateReference(exec);
790 KJS_CHECKEXCEPTIONVALUE
791 Value v = ref.getValue(exec);
792
793 bool knownToBeInteger;
794 double n = v.toNumber(exec, knownToBeInteger);
795
796 double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
797 ref.putValue(exec, Value(newValue, knownToBeInteger));
798
799 return Value(n, knownToBeInteger);
800}
801
802// ------------------------------ DeleteNode -----------------------------------
803
804void DeleteNode::ref()
805{
806 Node::ref();
807 if ( expr )
808 expr->ref();
809}
810
811bool DeleteNode::deref()
812{
813 if ( expr && expr->deref() )
814 delete expr;
815 return Node::deref();
816}
817
818// ECMA 11.4.1
819Value DeleteNode::evaluate(ExecState *exec)
820{
821 Reference ref = expr->evaluateReference(exec);
822 KJS_CHECKEXCEPTIONVALUE
823 return Value(ref.deleteValue(exec));
824}
825
826// ------------------------------ VoidNode -------------------------------------
827
828void VoidNode::ref()
829{
830 Node::ref();
831 if ( expr )
832 expr->ref();
833}
834
835bool VoidNode::deref()
836{
837 if ( expr && expr->deref() )
838 delete expr;
839 return Node::deref();
840}
841
842// ECMA 11.4.2
843Value VoidNode::evaluate(ExecState *exec)
844{
845 Value dummy1 = expr->evaluate(exec);
846 KJS_CHECKEXCEPTIONVALUE
847
848 return Undefined();
849}
850
851// ------------------------------ TypeOfNode -----------------------------------
852
853void TypeOfNode::ref()
854{
855 Node::ref();
856 if ( expr )
857 expr->ref();
858}
859
860bool TypeOfNode::deref()
861{
862 if ( expr && expr->deref() )
863 delete expr;
864 return Node::deref();
865}
866
867// ECMA 11.4.3
868Value TypeOfNode::evaluate(ExecState *exec)
869{
870 const char *s = 0L;
871 Reference ref = expr->evaluateReference(exec);
872 KJS_CHECKEXCEPTIONVALUE
873 ValueImp *b = ref.baseIfMutable();
874 if (b && b->dispatchType() == NullType)
875 return Value("undefined");
876 Value v = ref.getValue(exec);
877 switch (v.type())
878 {
879 case UndefinedType:
880 s = "undefined";
881 break;
882 case NullType:
883 s = "object";
884 break;
885 case BooleanType:
886 s = "boolean";
887 break;
888 case NumberType:
889 s = "number";
890 break;
891 case StringType:
892 s = "string";
893 break;
894 default:
895 if (v.type() == ObjectType && static_cast<ObjectImp*>(v.imp())->implementsCall())
896 s = "function";
897 else
898 s = "object";
899 break;
900 }
901
902 return Value(s);
903}
904
905// ------------------------------ PrefixNode -----------------------------------
906
907void PrefixNode::ref()
908{
909 Node::ref();
910 if ( expr )
911 expr->ref();
912}
913
914bool PrefixNode::deref()
915{
916 if ( expr && expr->deref() )
917 delete expr;
918 return Node::deref();
919}
920
921// ECMA 11.4.4 and 11.4.5
922Value PrefixNode::evaluate(ExecState *exec)
923{
924 Reference ref = expr->evaluateReference(exec);
925 KJS_CHECKEXCEPTIONVALUE
926 Value v = ref.getValue(exec);
927
928 bool knownToBeInteger;
929 double n = v.toNumber(exec, knownToBeInteger);
930
931 double newValue = (oper == OpPlusPlus) ? n + 1 : n - 1;
932 Value n2(newValue, knownToBeInteger);
933
934 ref.putValue(exec, n2);
935
936 return n2;
937}
938
939// ------------------------------ UnaryPlusNode --------------------------------
940
941void UnaryPlusNode::ref()
942{
943 Node::ref();
944 if ( expr )
945 expr->ref();
946}
947
948bool UnaryPlusNode::deref()
949{
950 if ( expr && expr->deref() )
951 delete expr;
952 return Node::deref();
953}
954
955// ECMA 11.4.6
956Value UnaryPlusNode::evaluate(ExecState *exec)
957{
958 Value v = expr->evaluate(exec);
959 KJS_CHECKEXCEPTIONVALUE
960
961 return Value(v.toNumber(exec)); /* TODO: optimize */
962}
963
964// ------------------------------ NegateNode -----------------------------------
965
966void NegateNode::ref()
967{
968 Node::ref();
969 if ( expr )
970 expr->ref();
971}
972
973bool NegateNode::deref()
974{
975 if ( expr && expr->deref() )
976 delete expr;
977 return Node::deref();
978}
979
980// ECMA 11.4.7
981Value NegateNode::evaluate(ExecState *exec)
982{
983 Value v = expr->evaluate(exec);
984 KJS_CHECKEXCEPTIONVALUE
985
986 bool knownToBeInteger;
987 double n = v.toNumber(exec, knownToBeInteger);
988 return Value(-n, knownToBeInteger && n != 0);
989}
990
991// ------------------------------ BitwiseNotNode -------------------------------
992
993void BitwiseNotNode::ref()
994{
995 Node::ref();
996 if ( expr )
997 expr->ref();
998}
999
1000bool BitwiseNotNode::deref()
1001{
1002 if ( expr && expr->deref() )
1003 delete expr;
1004 return Node::deref();
1005}
1006
1007// ECMA 11.4.8
1008Value BitwiseNotNode::evaluate(ExecState *exec)
1009{
1010 Value v = expr->evaluate(exec);
1011 KJS_CHECKEXCEPTIONVALUE
1012 return Value(~v.toInt32(exec));
1013}
1014
1015// ------------------------------ LogicalNotNode -------------------------------
1016
1017void LogicalNotNode::ref()
1018{
1019 Node::ref();
1020 if ( expr )
1021 expr->ref();
1022}
1023
1024bool LogicalNotNode::deref()
1025{
1026 if ( expr && expr->deref() )
1027 delete expr;
1028 return Node::deref();
1029}
1030
1031// ECMA 11.4.9
1032Value LogicalNotNode::evaluate(ExecState *exec)
1033{
1034 Value v = expr->evaluate(exec);
1035 KJS_CHECKEXCEPTIONVALUE
1036 return Value(!v.toBoolean(exec));
1037}
1038
1039// ------------------------------ MultNode -------------------------------------
1040
1041void MultNode::ref()
1042{
1043 Node::ref();
1044 if ( term1 )
1045 term1->ref();
1046 if ( term2 )
1047 term2->ref();
1048}
1049
1050bool MultNode::deref()
1051{
1052 if ( term1 && term1->deref() )
1053 delete term1;
1054 if ( term2 && term2->deref() )
1055 delete term2;
1056 return Node::deref();
1057}
1058
1059// ECMA 11.5
1060Value MultNode::evaluate(ExecState *exec)
1061{
1062 Value v1 = term1->evaluate(exec);
1063 KJS_CHECKEXCEPTIONVALUE
1064
1065 Value v2 = term2->evaluate(exec);
1066 KJS_CHECKEXCEPTIONVALUE
1067
1068 return mult(exec, v1, v2, oper);
1069}
1070
1071// ------------------------------ AddNode --------------------------------------
1072
1073void AddNode::ref()
1074{
1075 Node::ref();
1076 if ( term1 )
1077 term1->ref();
1078 if ( term2 )
1079 term2->ref();
1080}
1081
1082bool AddNode::deref()
1083{
1084 if ( term1 && term1->deref() )
1085 delete term1;
1086 if ( term2 && term2->deref() )
1087 delete term2;
1088 return Node::deref();
1089}
1090
1091// ECMA 11.6
1092Value AddNode::evaluate(ExecState *exec)
1093{
1094 Value v1 = term1->evaluate(exec);
1095 KJS_CHECKEXCEPTIONVALUE
1096
1097 Value v2 = term2->evaluate(exec);
1098 KJS_CHECKEXCEPTIONVALUE
1099
1100 return add(exec, v1, v2, oper);
1101}
1102
1103// ------------------------------ ShiftNode ------------------------------------
1104
1105void ShiftNode::ref()
1106{
1107 Node::ref();
1108 if ( term1 )
1109 term1->ref();
1110 if ( term2 )
1111 term2->ref();
1112}
1113
1114bool ShiftNode::deref()
1115{
1116 if ( term1 && term1->deref() )
1117 delete term1;
1118 if ( term2 && term2->deref() )
1119 delete term2;
1120 return Node::deref();
1121}
1122
1123// ECMA 11.7
1124Value ShiftNode::evaluate(ExecState *exec)
1125{
1126 Value v1 = term1->evaluate(exec);
1127 KJS_CHECKEXCEPTIONVALUE
1128 Value v2 = term2->evaluate(exec);
1129 KJS_CHECKEXCEPTIONVALUE
1130 unsigned int i2 = v2.toUInt32(exec);
1131 i2 &= 0x1f;
1132
1133 switch (oper) {
1134 case OpLShift:
1135 return Value(v1.toInt32(exec) << i2);
1136 case OpRShift:
1137 return Value(v1.toInt32(exec) >> i2);
1138 case OpURShift:
1139 return Value(v1.toUInt32(exec) >> i2);
1140 default:
1141 assert(!"ShiftNode: unhandled switch case");
1142 return Undefined();
1143 }
1144}
1145
1146// ------------------------------ RelationalNode -------------------------------
1147
1148void RelationalNode::ref()
1149{
1150 Node::ref();
1151 if ( expr1 )
1152 expr1->ref();
1153 if ( expr2 )
1154 expr2->ref();
1155}
1156
1157bool RelationalNode::deref()
1158{
1159 if ( expr1 && expr1->deref() )
1160 delete expr1;
1161 if ( expr2 && expr2->deref() )
1162 delete expr2;
1163 return Node::deref();
1164}
1165
1166// ECMA 11.8
1167Value RelationalNode::evaluate(ExecState *exec)
1168{
1169 Value v1 = expr1->evaluate(exec);
1170 KJS_CHECKEXCEPTIONVALUE
1171 Value v2 = expr2->evaluate(exec);
1172 KJS_CHECKEXCEPTIONVALUE
1173
1174 bool b;
1175 if (oper == OpLess || oper == OpGreaterEq) {
1176 int r = relation(exec, v1, v2);
1177 if (r < 0)
1178 b = false;
1179 else
1180 b = (oper == OpLess) ? (r == 1) : (r == 0);
1181 } else if (oper == OpGreater || oper == OpLessEq) {
1182 int r = relation(exec, v2, v1);
1183 if (r < 0)
1184 b = false;
1185 else
1186 b = (oper == OpGreater) ? (r == 1) : (r == 0);
1187 } else if (oper == OpIn) {
1188 // Is all of this OK for host objects?
1189 if (v2.type() != ObjectType)
1190 return throwError(exec, TypeError,
1191 "Value %s (result of expression %s) is not an object. Cannot be used with IN expression.", v2, expr2);
1192 Object o2(static_cast<ObjectImp*>(v2.imp()));
1193 b = o2.hasProperty(exec, Identifier(v1.toString(exec)));
1194 } else {
1195 if (v2.type() != ObjectType)
1196 return throwError(exec, TypeError,
1197 "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, expr2);
1198
1199 Object o2(static_cast<ObjectImp*>(v2.imp()));
1200 if (!o2.implementsHasInstance()) {
1201 // According to the spec, only some types of objects "imlement" the [[HasInstance]] property.
1202 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
1203 // property. It seems that all object have the property, but not all implement it, so in this
1204 // case we return false (consistent with mozilla)
1205 return Value(false);
1206 // return throwError(exec, TypeError,
1207 // "Object does not implement the [[HasInstance]] method." );
1208 }
1209 return o2.hasInstance(exec, v1);
1210 }
1211
1212 return Value(b);
1213}
1214
1215// ------------------------------ EqualNode ------------------------------------
1216
1217void EqualNode::ref()
1218{
1219 Node::ref();
1220 if ( expr1 )
1221 expr1->ref();
1222 if ( expr2 )
1223 expr2->ref();
1224}
1225
1226bool EqualNode::deref()
1227{
1228 if ( expr1 && expr1->deref() )
1229 delete expr1;
1230 if ( expr2 && expr2->deref() )
1231 delete expr2;
1232 return Node::deref();
1233}
1234
1235// ECMA 11.9
1236Value EqualNode::evaluate(ExecState *exec)
1237{
1238 Value v1 = expr1->evaluate(exec);
1239 KJS_CHECKEXCEPTIONVALUE
1240 Value v2 = expr2->evaluate(exec);
1241 KJS_CHECKEXCEPTIONVALUE
1242
1243 bool result;
1244 if (oper == OpEqEq || oper == OpNotEq) {
1245 // == and !=
1246 bool eq = equal(exec,v1, v2);
1247 result = oper == OpEqEq ? eq : !eq;
1248 } else {
1249 // === and !==
1250 bool eq = strictEqual(exec,v1, v2);
1251 result = oper == OpStrEq ? eq : !eq;
1252 }
1253 return Value(result);
1254}
1255
1256// ------------------------------ BitOperNode ----------------------------------
1257
1258void BitOperNode::ref()
1259{
1260 Node::ref();
1261 if ( expr1 )
1262 expr1->ref();
1263 if ( expr2 )
1264 expr2->ref();
1265}
1266
1267bool BitOperNode::deref()
1268{
1269 if ( expr1 && expr1->deref() )
1270 delete expr1;
1271 if ( expr2 && expr2->deref() )
1272 delete expr2;
1273 return Node::deref();
1274}
1275
1276// ECMA 11.10
1277Value BitOperNode::evaluate(ExecState *exec)
1278{
1279 Value v1 = expr1->evaluate(exec);
1280 KJS_CHECKEXCEPTIONVALUE
1281 Value v2 = expr2->evaluate(exec);
1282 KJS_CHECKEXCEPTIONVALUE
1283 int i1 = v1.toInt32(exec);
1284 int i2 = v2.toInt32(exec);
1285 int result;
1286 if (oper == OpBitAnd)
1287 result = i1 & i2;
1288 else if (oper == OpBitXOr)
1289 result = i1 ^ i2;
1290 else
1291 result = i1 | i2;
1292
1293 return Value(result);
1294}
1295
1296// ------------------------------ BinaryLogicalNode ----------------------------
1297
1298void BinaryLogicalNode::ref()
1299{
1300 Node::ref();
1301 if ( expr1 )
1302 expr1->ref();
1303 if ( expr2 )
1304 expr2->ref();
1305}
1306
1307bool BinaryLogicalNode::deref()
1308{
1309 if ( expr1 && expr1->deref() )
1310 delete expr1;
1311 if ( expr2 && expr2->deref() )
1312 delete expr2;
1313 return Node::deref();
1314}
1315
1316// ECMA 11.11
1317Value BinaryLogicalNode::evaluate(ExecState *exec)
1318{
1319 Value v1 = expr1->evaluate(exec);
1320 KJS_CHECKEXCEPTIONVALUE
1321 bool b1 = v1.toBoolean(exec);
1322 if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
1323 return v1;
1324
1325 Value v2 = expr2->evaluate(exec);
1326 KJS_CHECKEXCEPTIONVALUE
1327
1328 return v2;
1329}
1330
1331// ------------------------------ ConditionalNode ------------------------------
1332
1333void ConditionalNode::ref()
1334{
1335 Node::ref();
1336 if ( expr1 )
1337 expr1->ref();
1338 if ( expr2 )
1339 expr2->ref();
1340 if ( logical )
1341 logical->ref();
1342}
1343
1344bool ConditionalNode::deref()
1345{
1346 if ( expr1 && expr1->deref() )
1347 delete expr1;
1348 if ( expr2 && expr2->deref() )
1349 delete expr2;
1350 if ( logical && logical->deref() )
1351 delete logical;
1352 return Node::deref();
1353}
1354
1355// ECMA 11.12
1356Value ConditionalNode::evaluate(ExecState *exec)
1357{
1358 Value v = logical->evaluate(exec);
1359 KJS_CHECKEXCEPTIONVALUE
1360 bool b = v.toBoolean(exec);
1361
1362 if (b)
1363 v = expr1->evaluate(exec);
1364 else
1365 v = expr2->evaluate(exec);
1366 KJS_CHECKEXCEPTIONVALUE
1367
1368 return v;
1369}
1370
1371// ------------------------------ AssignNode -----------------------------------
1372
1373void AssignNode::ref()
1374{
1375 Node::ref();
1376 if ( left )
1377 left->ref();
1378 if ( expr )
1379 expr->ref();
1380}
1381
1382bool AssignNode::deref()
1383{
1384 if ( left && left->deref() )
1385 delete left;
1386 if ( expr && expr->deref() )
1387 delete expr;
1388 return Node::deref();
1389}
1390
1391// ECMA 11.13
1392Value AssignNode::evaluate(ExecState *exec)
1393{
1394 Reference l = left->evaluateReference(exec);
1395 KJS_CHECKEXCEPTIONVALUE
1396 Value e, v;
1397 if (oper == OpEqual) {
1398 v = expr->evaluate(exec);
1399 KJS_CHECKEXCEPTIONVALUE
1400 } else {
1401 Value v1 = l.getValue(exec);
1402 Value v2 = expr->evaluate(exec);
1403 KJS_CHECKEXCEPTIONVALUE
1404 int i1;
1405 int i2;
1406 unsigned int ui;
1407 switch (oper) {
1408 case OpMultEq:
1409 v = mult(exec, v1, v2, '*');
1410 break;
1411 case OpDivEq:
1412 v = mult(exec, v1, v2, '/');
1413 break;
1414 case OpPlusEq:
1415 v = add(exec, v1, v2, '+');
1416 break;
1417 case OpMinusEq:
1418 v = add(exec, v1, v2, '-');
1419 break;
1420 case OpLShift:
1421 i1 = v1.toInt32(exec);
1422 i2 = v2.toInt32(exec);
1423 v = Value(i1 << i2);
1424 break;
1425 case OpRShift:
1426 i1 = v1.toInt32(exec);
1427 i2 = v2.toInt32(exec);
1428 v = Value(i1 >> i2);
1429 break;
1430 case OpURShift:
1431 ui = v1.toUInt32(exec);
1432 i2 = v2.toInt32(exec);
1433 v = Value(ui >> i2);
1434 break;
1435 case OpAndEq:
1436 i1 = v1.toInt32(exec);
1437 i2 = v2.toInt32(exec);
1438 v = Value(i1 & i2);
1439 break;
1440 case OpXOrEq:
1441 i1 = v1.toInt32(exec);
1442 i2 = v2.toInt32(exec);
1443 v = Value(i1 ^ i2);
1444 break;
1445 case OpOrEq:
1446 i1 = v1.toInt32(exec);
1447 i2 = v2.toInt32(exec);
1448 v = Value(i1 | i2);
1449 break;
1450 case OpModEq: {
1451 bool d1KnownToBeInteger;
1452 double d1 = v1.toNumber(exec, d1KnownToBeInteger);
1453 bool d2KnownToBeInteger;
1454 double d2 = v2.toNumber(exec, d2KnownToBeInteger);
1455 v = Value(fmod(d1, d2), d1KnownToBeInteger && d2KnownToBeInteger && d2 != 0);
1456 }
1457 break;
1458 default:
1459 v = Undefined();
1460 }
1461 };
1462 l.putValue(exec,v);
1463
1464 KJS_CHECKEXCEPTIONVALUE
1465
1466 return v;
1467}
1468
1469// ------------------------------ CommaNode ------------------------------------
1470
1471void CommaNode::ref()
1472{
1473 Node::ref();
1474 if ( expr1 )
1475 expr1->ref();
1476 if ( expr2 )
1477 expr2->ref();
1478}
1479
1480bool CommaNode::deref()
1481{
1482 if ( expr1 && expr1->deref() )
1483 delete expr1;
1484 if ( expr2 && expr2->deref() )
1485 delete expr2;
1486 return Node::deref();
1487}
1488
1489// ECMA 11.14
1490Value CommaNode::evaluate(ExecState *exec)
1491{
1492 Value dummy = expr1->evaluate(exec);
1493 KJS_CHECKEXCEPTIONVALUE
1494 Value v = expr2->evaluate(exec);
1495 KJS_CHECKEXCEPTIONVALUE
1496
1497 return v;
1498}
1499
1500// ------------------------------ StatListNode ---------------------------------
1501
1502StatListNode::StatListNode(StatementNode *s)
1503 : statement(s), list(this)
1504{
1505 setLoc(s->firstLine(), s->lastLine(), s->sourceId());
1506}
1507
1508StatListNode::StatListNode(StatListNode *l, StatementNode *s)
1509 : statement(s), list(l->list)
1510{
1511 l->list = this;
1512 setLoc(l->firstLine(), s->lastLine(), l->sourceId());
1513}
1514
1515void StatListNode::ref()
1516{
1517 for (StatListNode *n = this; n; n = n->list) {
1518 n->Node::ref();
1519 if (n->statement)
1520 n->statement->ref();
1521 }
1522}
1523
1524bool StatListNode::deref()
1525{
1526 StatListNode *next;
1527 for (StatListNode *n = this; n; n = next) {
1528 next = n->list;
1529 if (n->statement && n->statement->deref())
1530 delete n->statement;
1531 if (n != this && n->Node::deref())
1532 delete n;
1533 }
1534 return Node::deref();
1535}
1536
1537// ECMA 12.1
1538Completion StatListNode::execute(ExecState *exec)
1539{
1540 Completion c = statement->execute(exec);
1541 KJS_ABORTPOINT
1542 if (exec->hadException()) {
1543 Value ex = exec->exception();
1544 exec->clearException();
1545 return Completion(Throw, ex);
1546 }
1547
1548 if (c.complType() != Normal)
1549 return c;
1550
1551 Value v = c.value();
1552
1553 for (StatListNode *n = list; n; n = n->list) {
1554 Completion c2 = n->statement->execute(exec);
1555 KJS_ABORTPOINT
1556 if (c2.complType() != Normal)
1557 return c2;
1558
1559 if (exec->hadException()) {
1560 Value ex = exec->exception();
1561 exec->clearException();
1562 return Completion(Throw, ex);
1563 }
1564
1565 if (c2.isValueCompletion())
1566 v = c2.value();
1567 c = c2;
1568 }
1569
1570 return Completion(c.complType(), v, c.target());
1571}
1572
1573void StatListNode::processVarDecls(ExecState *exec)
1574{
1575 for (StatListNode *n = this; n; n = n->list)
1576 n->statement->processVarDecls(exec);
1577}
1578
1579// ------------------------------ AssignExprNode -------------------------------
1580
1581void AssignExprNode::ref()
1582{
1583 Node::ref();
1584 if ( expr )
1585 expr->ref();
1586}
1587
1588bool AssignExprNode::deref()
1589{
1590 if ( expr && expr->deref() )
1591 delete expr;
1592 return Node::deref();
1593}
1594
1595// ECMA 12.2
1596Value AssignExprNode::evaluate(ExecState *exec)
1597{
1598 return expr->evaluate(exec);
1599}
1600
1601// ------------------------------ VarDeclNode ----------------------------------
1602
1603
1604VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in, Type t)
1605 : varType(t), ident(id), init(in)
1606{
1607}
1608
1609void VarDeclNode::ref()
1610{
1611 Node::ref();
1612 if ( init )
1613 init->ref();
1614}
1615
1616bool VarDeclNode::deref()
1617{
1618 if ( init && init->deref() )
1619 delete init;
1620 return Node::deref();
1621}
1622
1623// ECMA 12.2
1624Value VarDeclNode::evaluate(ExecState *exec)
1625{
1626 Object variable = exec->context().imp()->variableObject();
1627
1628 Value val;
1629 if (init) {
1630 val = init->evaluate(exec);
1631 KJS_CHECKEXCEPTIONVALUE
1632 } else {
1633 // already declared? - check with getDirect so you can override
1634 // built-in properties of the global object with var declarations.
1635 if ( variable.imp()->getDirect(ident) )
1636 return Value();
1637 val = Undefined();
1638 }
1639
1640#ifdef KJS_VERBOSE
1641 printInfo(exec,(UString("new variable ")+ident.ustring()).cstring().c_str(),val);
1642#endif
1643 // We use Internal to bypass all checks in derived objects, e.g. so that
1644 // "var location" creates a dynamic property instead of activating window.location.
1645 int flags = Internal;
1646 if (exec->context().imp()->codeType() != EvalCode)
1647 flags |= DontDelete;
1648 if (varType == VarDeclNode::Constant)
1649 flags |= ReadOnly;
1650 variable.put(exec, ident, val, flags);
1651
1652 return ident.ustring();
1653}
1654
1655void VarDeclNode::processVarDecls(ExecState *exec)
1656{
1657 Object variable = exec->context().imp()->variableObject();
1658
1659 // If a variable by this name already exists, don't clobber it -
1660 // it might be a function parameter
1661 if (!variable.hasProperty(exec, ident)) {
1662 int flags = Internal;
1663 if (exec->context().imp()->codeType() != EvalCode)
1664 flags |= DontDelete;
1665 if (varType == VarDeclNode::Constant)
1666 flags |= ReadOnly;
1667 variable.put(exec, ident, Undefined(), flags);
1668 }
1669}
1670
1671// ------------------------------ VarDeclListNode ------------------------------
1672
1673void VarDeclListNode::ref()
1674{
1675 for (VarDeclListNode *n = this; n; n = n->list) {
1676 n->Node::ref();
1677 if (n->var)
1678 n->var->ref();
1679 }
1680}
1681
1682bool VarDeclListNode::deref()
1683{
1684 VarDeclListNode *next;
1685 for (VarDeclListNode *n = this; n; n = next) {
1686 next = n->list;
1687 if (n->var && n->var->deref())
1688 delete n->var;
1689 if (n != this && n->Node::deref())
1690 delete n;
1691 }
1692 return Node::deref();
1693}
1694
1695
1696// ECMA 12.2
1697Value VarDeclListNode::evaluate(ExecState *exec)
1698{
1699 for (VarDeclListNode *n = this; n; n = n->list) {
1700 n->var->evaluate(exec);
1701 KJS_CHECKEXCEPTIONVALUE
1702 }
1703 return Undefined();
1704}
1705
1706void VarDeclListNode::processVarDecls(ExecState *exec)
1707{
1708 for (VarDeclListNode *n = this; n; n = n->list)
1709 n->var->processVarDecls(exec);
1710}
1711
1712// ------------------------------ VarStatementNode -----------------------------
1713
1714void VarStatementNode::ref()
1715{
1716 Node::ref();
1717 if ( list )
1718 list->ref();
1719}
1720
1721bool VarStatementNode::deref()
1722{
1723 if ( list && list->deref() )
1724 delete list;
1725 return Node::deref();
1726}
1727
1728// ECMA 12.2
1729Completion VarStatementNode::execute(ExecState *exec)
1730{
1731 KJS_BREAKPOINT;
1732
1733 (void) list->evaluate(exec);
1734 KJS_CHECKEXCEPTION
1735
1736 return Completion(Normal);
1737}
1738
1739void VarStatementNode::processVarDecls(ExecState *exec)
1740{
1741 list->processVarDecls(exec);
1742}
1743
1744// ------------------------------ BlockNode ------------------------------------
1745
1746BlockNode::BlockNode(SourceElementsNode *s)
1747{
1748 if (s) {
1749 source = s->elements;
1750 s->elements = 0;
1751 setLoc(s->firstLine(), s->lastLine(), s->sourceId());
1752 } else {
1753 source = 0;
1754 }
1755}
1756
1757void BlockNode::ref()
1758{
1759 Node::ref();
1760 if ( source )
1761 source->ref();
1762}
1763
1764bool BlockNode::deref()
1765{
1766 if ( source && source->deref() )
1767 delete source;
1768 return Node::deref();
1769}
1770
1771// ECMA 12.1
1772Completion BlockNode::execute(ExecState *exec)
1773{
1774 if (!source)
1775 return Completion(Normal);
1776
1777 source->processFuncDecl(exec);
1778
1779 return source->execute(exec);
1780}
1781
1782void BlockNode::processVarDecls(ExecState *exec)
1783{
1784 if (source)
1785 source->processVarDecls(exec);
1786}
1787
1788// ------------------------------ EmptyStatementNode ---------------------------
1789
1790// ECMA 12.3
1791Completion EmptyStatementNode::execute(ExecState */*exec*/)
1792{
1793 return Completion(Normal);
1794}
1795
1796// ------------------------------ ExprStatementNode ----------------------------
1797
1798void ExprStatementNode::ref()
1799{
1800 Node::ref();
1801 if ( expr )
1802 expr->ref();
1803}
1804
1805bool ExprStatementNode::deref()
1806{
1807 if ( expr && expr->deref() )
1808 delete expr;
1809 return Node::deref();
1810}
1811
1812// ECMA 12.4
1813Completion ExprStatementNode::execute(ExecState *exec)
1814{
1815 KJS_BREAKPOINT;
1816
1817 Value v = expr->evaluate(exec);
1818 KJS_CHECKEXCEPTION
1819
1820 return Completion(Normal, v);
1821}
1822
1823// ------------------------------ IfNode ---------------------------------------
1824
1825void IfNode::ref()
1826{
1827 Node::ref();
1828 if ( statement1 )
1829 statement1->ref();
1830 if ( statement2 )
1831 statement2->ref();
1832 if ( expr )
1833 expr->ref();
1834}
1835
1836bool IfNode::deref()
1837{
1838 if ( statement1 && statement1->deref() )
1839 delete statement1;
1840 if ( statement2 && statement2->deref() )
1841 delete statement2;
1842 if ( expr && expr->deref() )
1843 delete expr;
1844 return Node::deref();
1845}
1846
1847// ECMA 12.5
1848Completion IfNode::execute(ExecState *exec)
1849{
1850 KJS_BREAKPOINT;
1851
1852 Value v = expr->evaluate(exec);
1853 KJS_CHECKEXCEPTION
1854 bool b = v.toBoolean(exec);
1855
1856 // if ... then
1857 if (b)
1858 return statement1->execute(exec);
1859
1860 // no else
1861 if (!statement2)
1862 return Completion(Normal);
1863
1864 // else
1865 return statement2->execute(exec);
1866}
1867
1868void IfNode::processVarDecls(ExecState *exec)
1869{
1870 statement1->processVarDecls(exec);
1871
1872 if (statement2)
1873 statement2->processVarDecls(exec);
1874}
1875
1876// ------------------------------ DoWhileNode ----------------------------------
1877
1878void DoWhileNode::ref()
1879{
1880 Node::ref();
1881 if ( statement )
1882 statement->ref();
1883 if ( expr )
1884 expr->ref();
1885}
1886
1887bool DoWhileNode::deref()
1888{
1889 if ( statement && statement->deref() )
1890 delete statement;
1891 if ( expr && expr->deref() )
1892 delete expr;
1893 return Node::deref();
1894}
1895
1896// ECMA 12.6.1
1897Completion DoWhileNode::execute(ExecState *exec)
1898{
1899 KJS_BREAKPOINT;
1900
1901 Value be, bv;
1902 Completion c;
1903 Value value;
1904
1905 do {
1906 // bail out on error
1907 KJS_CHECKEXCEPTION
1908
1909 exec->context().imp()->seenLabels()->pushIteration();
1910 c = statement->execute(exec);
1911 exec->context().imp()->seenLabels()->popIteration();
1912 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1913 if ((c.complType() == Break) && ls.contains(c.target()))
1914 return Completion(Normal, value);
1915 if (c.complType() != Normal)
1916 return c;
1917 }
1918 bv = expr->evaluate(exec);
1919 KJS_CHECKEXCEPTION
1920 } while (bv.toBoolean(exec));
1921
1922 return Completion(Normal, value);
1923}
1924
1925void DoWhileNode::processVarDecls(ExecState *exec)
1926{
1927 statement->processVarDecls(exec);
1928}
1929
1930// ------------------------------ WhileNode ------------------------------------
1931
1932void WhileNode::ref()
1933{
1934 Node::ref();
1935 if ( statement )
1936 statement->ref();
1937 if ( expr )
1938 expr->ref();
1939}
1940
1941bool WhileNode::deref()
1942{
1943 if ( statement && statement->deref() )
1944 delete statement;
1945 if ( expr && expr->deref() )
1946 delete expr;
1947 return Node::deref();
1948}
1949
1950// ECMA 12.6.2
1951Completion WhileNode::execute(ExecState *exec)
1952{
1953 KJS_BREAKPOINT;
1954
1955 Value be, bv;
1956 Completion c;
1957 bool b(false);
1958 Value value;
1959
1960 while (1) {
1961 bv = expr->evaluate(exec);
1962 KJS_CHECKEXCEPTION
1963 b = bv.toBoolean(exec);
1964
1965 // bail out on error
1966 KJS_CHECKEXCEPTION
1967
1968 if (!b)
1969 return Completion(Normal, value);
1970
1971 exec->context().imp()->seenLabels()->pushIteration();
1972 c = statement->execute(exec);
1973 exec->context().imp()->seenLabels()->popIteration();
1974 if (c.isValueCompletion())
1975 value = c.value();
1976
1977 if ((c.complType() == Continue) && ls.contains(c.target()))
1978 continue;
1979 if ((c.complType() == Break) && ls.contains(c.target()))
1980 return Completion(Normal, value);
1981 if (c.complType() != Normal)
1982 return c;
1983 }
1984
1985 return Completion(); // work around gcc 4.0 bug
1986}
1987
1988void WhileNode::processVarDecls(ExecState *exec)
1989{
1990 statement->processVarDecls(exec);
1991}
1992
1993// ------------------------------ ForNode --------------------------------------
1994
1995void ForNode::ref()
1996{
1997 Node::ref();
1998 if ( statement )
1999 statement->ref();
2000 if ( expr1 )
2001 expr1->ref();
2002 if ( expr2 )
2003 expr2->ref();
2004 if ( expr3 )
2005 expr3->ref();
2006}
2007
2008bool ForNode::deref()
2009{
2010 if ( statement && statement->deref() )
2011 delete statement;
2012 if ( expr1 && expr1->deref() )
2013 delete expr1;
2014 if ( expr2 && expr2->deref() )
2015 delete expr2;
2016 if ( expr3 && expr3->deref() )
2017 delete expr3;
2018 return Node::deref();
2019}
2020
2021// ECMA 12.6.3
2022Completion ForNode::execute(ExecState *exec)
2023{
2024 Value v, cval;
2025
2026 if (expr1) {
2027 v = expr1->evaluate(exec);
2028 KJS_CHECKEXCEPTION
2029 }
2030 while (1) {
2031 if (expr2) {
2032 v = expr2->evaluate(exec);
2033 KJS_CHECKEXCEPTION
2034 if (!v.toBoolean(exec))
2035 return Completion(Normal, cval);
2036 }
2037 // bail out on error
2038 KJS_CHECKEXCEPTION
2039
2040 exec->context().imp()->seenLabels()->pushIteration();
2041 Completion c = statement->execute(exec);
2042 exec->context().imp()->seenLabels()->popIteration();
2043 if (c.isValueCompletion())
2044 cval = c.value();
2045 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2046 if ((c.complType() == Break) && ls.contains(c.target()))
2047 return Completion(Normal, cval);
2048 if (c.complType() != Normal)
2049 return c;
2050 }
2051 if (expr3) {
2052 v = expr3->evaluate(exec);
2053 KJS_CHECKEXCEPTION
2054 }
2055 }
2056
2057 return Completion(); // work around gcc 4.0 bug
2058}
2059
2060void ForNode::processVarDecls(ExecState *exec)
2061{
2062 if (expr1)
2063 expr1->processVarDecls(exec);
2064
2065 statement->processVarDecls(exec);
2066}
2067
2068// ------------------------------ ForInNode ------------------------------------
2069
2070ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
2071 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
2072{
2073}
2074
2075ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
2076 : ident(i), init(in), expr(e), statement(s)
2077{
2078 // for( var foo = bar in baz )
2079 varDecl = new VarDeclNode(ident, init, VarDeclNode::Variable);
2080 lexpr = new ResolveNode(ident);
2081}
2082
2083void ForInNode::ref()
2084{
2085 Node::ref();
2086 if ( statement )
2087 statement->ref();
2088 if ( expr )
2089 expr->ref();
2090 if ( lexpr )
2091 lexpr->ref();
2092 if ( init )
2093 init->ref();
2094 if ( varDecl )
2095 varDecl->ref();
2096}
2097
2098bool ForInNode::deref()
2099{
2100 if ( statement && statement->deref() )
2101 delete statement;
2102 if ( expr && expr->deref() )
2103 delete expr;
2104 if ( lexpr && lexpr->deref() )
2105 delete lexpr;
2106 if ( init && init->deref() )
2107 delete init;
2108 if ( varDecl && varDecl->deref() )
2109 delete varDecl;
2110 return Node::deref();
2111}
2112
2113// ECMA 12.6.4
2114Completion ForInNode::execute(ExecState *exec)
2115{
2116 Value e, retval;
2117 Object v;
2118 Completion c;
2119 ReferenceList propList;
2120
2121 if ( varDecl ) {
2122 varDecl->evaluate(exec);
2123 KJS_CHECKEXCEPTION
2124 }
2125
2126 e = expr->evaluate(exec);
2127
2128 // for Null and Undefined, we want to make sure not to go through
2129 // the loop at all, because their object wrappers will have a
2130 // property list but will throw an exception if you attempt to
2131 // access any property.
2132 if (e.type() == UndefinedType || e.type() == NullType) {
2133 return Completion(Normal, retval);
2134 }
2135
2136 KJS_CHECKEXCEPTION
2137 v = e.toObject(exec);
2138 propList = v.propList(exec);
2139
2140 ReferenceListIterator propIt = propList.begin();
2141
2142 while (propIt != propList.end()) {
2143 Identifier name = propIt->getPropertyName(exec);
2144 if (!v.hasProperty(exec,name)) {
2145 propIt++;
2146 continue;
2147 }
2148
2149 Reference ref = lexpr->evaluateReference(exec);
2150 KJS_CHECKEXCEPTION
2151 ref.putValue(exec, String(name.ustring()));
2152
2153 exec->context().imp()->seenLabels()->pushIteration();
2154 c = statement->execute(exec);
2155 exec->context().imp()->seenLabels()->popIteration();
2156 if (c.isValueCompletion())
2157 retval = c.value();
2158
2159 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
2160 if ((c.complType() == Break) && ls.contains(c.target()))
2161 break;
2162 if (c.complType() != Normal) {
2163 return c;
2164 }
2165 }
2166
2167 propIt++;
2168 }
2169
2170 // bail out on error
2171 KJS_CHECKEXCEPTION
2172
2173 return Completion(Normal, retval);
2174}
2175
2176void ForInNode::processVarDecls(ExecState *exec)
2177{
2178 statement->processVarDecls(exec);
2179}
2180
2181// ------------------------------ ContinueNode ---------------------------------
2182
2183// ECMA 12.7
2184Completion ContinueNode::execute(ExecState *exec)
2185{
2186 KJS_BREAKPOINT;
2187
2188 Value dummy;
2189
2190 if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration())
2191 return Completion(Throw,
2192 throwError(exec, SyntaxError, "Invalid continue statement."));
2193 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
2194 return Completion(Throw,
2195 throwError(exec, SyntaxError, "Label %s not found.", ident));
2196 else
2197 return Completion(Continue, dummy, ident);
2198}
2199
2200// ------------------------------ BreakNode ------------------------------------
2201
2202// ECMA 12.8
2203Completion BreakNode::execute(ExecState *exec)
2204{
2205 KJS_BREAKPOINT;
2206
2207 Value dummy;
2208
2209 if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration() &&
2210 !exec->context().imp()->seenLabels()->inSwitch())
2211 return Completion(Throw,
2212 throwError(exec, SyntaxError, "Invalid break statement."));
2213 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
2214 return Completion(Throw,
2215 throwError(exec, SyntaxError, "Label %s not found.", ident));
2216 else
2217 return Completion(Break, dummy, ident);
2218}
2219
2220// ------------------------------ ReturnNode -----------------------------------
2221
2222void ReturnNode::ref()
2223{
2224 Node::ref();
2225 if ( value )
2226 value->ref();
2227}
2228
2229bool ReturnNode::deref()
2230{
2231 if ( value && value->deref() )
2232 delete value;
2233 return Node::deref();
2234}
2235
2236// ECMA 12.9
2237Completion ReturnNode::execute(ExecState *exec)
2238{
2239 KJS_BREAKPOINT;
2240
2241 CodeType codeType = exec->context().imp()->codeType();
2242 if (codeType != FunctionCode && codeType != AnonymousCode ) {
2243 return Completion(Throw, throwError(exec, SyntaxError, "Invalid return statement."));
2244 }
2245
2246 if (!value)
2247 return Completion(ReturnValue, Undefined());
2248
2249 Value v = value->evaluate(exec);
2250 KJS_CHECKEXCEPTION
2251
2252 return Completion(ReturnValue, v);
2253}
2254
2255// ------------------------------ WithNode -------------------------------------
2256
2257void WithNode::ref()
2258{
2259 Node::ref();
2260 if ( statement )
2261 statement->ref();
2262 if ( expr )
2263 expr->ref();
2264}
2265
2266bool WithNode::deref()
2267{
2268 if ( statement && statement->deref() )
2269 delete statement;
2270 if ( expr && expr->deref() )
2271 delete expr;
2272 return Node::deref();
2273}
2274
2275// ECMA 12.10
2276Completion WithNode::execute(ExecState *exec)
2277{
2278 KJS_BREAKPOINT;
2279
2280 Value v = expr->evaluate(exec);
2281 KJS_CHECKEXCEPTION
2282 Object o = v.toObject(exec);
2283 KJS_CHECKEXCEPTION
2284 exec->context().imp()->pushScope(o);
2285 Completion res = statement->execute(exec);
2286 exec->context().imp()->popScope();
2287
2288 return res;
2289}
2290
2291void WithNode::processVarDecls(ExecState *exec)
2292{
2293 statement->processVarDecls(exec);
2294}
2295
2296// ------------------------------ CaseClauseNode -------------------------------
2297
2298void CaseClauseNode::ref()
2299{
2300 Node::ref();
2301 if ( expr )
2302 expr->ref();
2303 if ( list )
2304 list->ref();
2305}
2306
2307bool CaseClauseNode::deref()
2308{
2309 if ( expr && expr->deref() )
2310 delete expr;
2311 if ( list && list->deref() )
2312 delete list;
2313 return Node::deref();
2314}
2315
2316// ECMA 12.11
2317Value CaseClauseNode::evaluate(ExecState *exec)
2318{
2319 Value v = expr->evaluate(exec);
2320 KJS_CHECKEXCEPTIONVALUE
2321
2322 return v;
2323}
2324
2325// ECMA 12.11
2326Completion CaseClauseNode::evalStatements(ExecState *exec)
2327{
2328 if (list)
2329 return list->execute(exec);
2330 else
2331 return Completion(Normal, Undefined());
2332}
2333
2334void CaseClauseNode::processVarDecls(ExecState *exec)
2335{
2336 if (list)
2337 list->processVarDecls(exec);
2338}
2339
2340// ------------------------------ ClauseListNode -------------------------------
2341
2342void ClauseListNode::ref()
2343{
2344 for (ClauseListNode *n = this; n; n = n->nx) {
2345 n->Node::ref();
2346 if (n->cl)
2347 n->cl->ref();
2348 }
2349}
2350
2351bool ClauseListNode::deref()
2352{
2353 ClauseListNode *next;
2354 for (ClauseListNode *n = this; n; n = next) {
2355 next = n->nx;
2356 if (n->cl && n->cl->deref())
2357 delete n->cl;
2358 if (n != this && n->Node::deref())
2359 delete n;
2360 }
2361 return Node::deref();
2362}
2363
2364Value ClauseListNode::evaluate(ExecState */*exec*/)
2365{
2366 /* should never be called */
2367 assert(false);
2368 return Value();
2369}
2370
2371// ECMA 12.11
2372void ClauseListNode::processVarDecls(ExecState *exec)
2373{
2374 for (ClauseListNode *n = this; n; n = n->nx)
2375 if (n->cl)
2376 n->cl->processVarDecls(exec);
2377}
2378
2379// ------------------------------ CaseBlockNode --------------------------------
2380
2381CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
2382 ClauseListNode *l2)
2383{
2384 if (l1) {
2385 list1 = l1->nx;
2386 l1->nx = 0;
2387 } else {
2388 list1 = 0;
2389 }
2390
2391 def = d;
2392
2393 if (l2) {
2394 list2 = l2->nx;
2395 l2->nx = 0;
2396 } else {
2397 list2 = 0;
2398 }
2399}
2400
2401void CaseBlockNode::ref()
2402{
2403 Node::ref();
2404 if ( def )
2405 def->ref();
2406 if ( list1 )
2407 list1->ref();
2408 if ( list2 )
2409 list2->ref();
2410}
2411
2412bool CaseBlockNode::deref()
2413{
2414 if ( def && def->deref() )
2415 delete def;
2416 if ( list1 && list1->deref() )
2417 delete list1;
2418 if ( list2 && list2->deref() )
2419 delete list2;
2420 return Node::deref();
2421}
2422
2423Value CaseBlockNode::evaluate(ExecState */*exec*/)
2424{
2425 /* should never be called */
2426 assert(false);
2427 return Value();
2428}
2429
2430// ECMA 12.11
2431Completion CaseBlockNode::evalBlock(ExecState *exec, const Value& input)
2432{
2433 Value v;
2434 Completion res;
2435 ClauseListNode *a = list1, *b = list2;
2436 CaseClauseNode *clause;
2437
2438 while (a) {
2439 clause = a->clause();
2440 a = a->next();
2441 v = clause->evaluate(exec);
2442 KJS_CHECKEXCEPTION
2443 if (strictEqual(exec, input, v)) {
2444 res = clause->evalStatements(exec);
2445 if (res.complType() != Normal)
2446 return res;
2447 while (a) {
2448 res = a->clause()->evalStatements(exec);
2449 if (res.complType() != Normal)
2450 return res;
2451 a = a->next();
2452 }
2453 break;
2454 }
2455 }
2456
2457 while (b) {
2458 clause = b->clause();
2459 b = b->next();
2460 v = clause->evaluate(exec);
2461 KJS_CHECKEXCEPTION
2462 if (strictEqual(exec, input, v)) {
2463 res = clause->evalStatements(exec);
2464 if (res.complType() != Normal)
2465 return res;
2466 goto step18;
2467 }
2468 }
2469
2470 // default clause
2471 if (def) {
2472 res = def->evalStatements(exec);
2473 if (res.complType() != Normal)
2474 return res;
2475 }
2476 b = list2;
2477 step18:
2478 while (b) {
2479 clause = b->clause();
2480 res = clause->evalStatements(exec);
2481 if (res.complType() != Normal)
2482 return res;
2483 b = b->next();
2484 }
2485
2486 // bail out on error
2487 KJS_CHECKEXCEPTION
2488
2489 return Completion(Normal);
2490}
2491
2492void CaseBlockNode::processVarDecls(ExecState *exec)
2493{
2494 if (list1)
2495 list1->processVarDecls(exec);
2496 if (def)
2497 def->processVarDecls(exec);
2498 if (list2)
2499 list2->processVarDecls(exec);
2500}
2501
2502// ------------------------------ SwitchNode -----------------------------------
2503
2504void SwitchNode::ref()
2505{
2506 Node::ref();
2507 if ( expr )
2508 expr->ref();
2509 if ( block )
2510 block->ref();
2511}
2512
2513bool SwitchNode::deref()
2514{
2515 if ( expr && expr->deref() )
2516 delete expr;
2517 if ( block && block->deref() )
2518 delete block;
2519 return Node::deref();
2520}
2521
2522// ECMA 12.11
2523Completion SwitchNode::execute(ExecState *exec)
2524{
2525 KJS_BREAKPOINT;
2526
2527 Value v = expr->evaluate(exec);
2528 KJS_CHECKEXCEPTION
2529
2530 exec->context().imp()->seenLabels()->pushSwitch();
2531 Completion res = block->evalBlock(exec,v);
2532 exec->context().imp()->seenLabels()->popSwitch();
2533
2534 if ((res.complType() == Break) && ls.contains(res.target()))
2535 return Completion(Normal, res.value());
2536 return res;
2537}
2538
2539void SwitchNode::processVarDecls(ExecState *exec)
2540{
2541 block->processVarDecls(exec);
2542}
2543
2544// ------------------------------ LabelNode ------------------------------------
2545
2546void LabelNode::ref()
2547{
2548 Node::ref();
2549 if ( statement )
2550 statement->ref();
2551}
2552
2553bool LabelNode::deref()
2554{
2555 if ( statement && statement->deref() )
2556 delete statement;
2557 return Node::deref();
2558}
2559
2560// ECMA 12.12
2561Completion LabelNode::execute(ExecState *exec)
2562{
2563 Completion e;
2564
2565 if (!exec->context().imp()->seenLabels()->push(label)) {
2566 return Completion( Throw,
2567 throwError(exec, SyntaxError, "Duplicated label %s found.", label));
2568 };
2569 e = statement->execute(exec);
2570 exec->context().imp()->seenLabels()->pop();
2571
2572 if ((e.complType() == Break) && (e.target() == label))
2573 return Completion(Normal, e.value());
2574 return e;
2575}
2576
2577void LabelNode::processVarDecls(ExecState *exec)
2578{
2579 statement->processVarDecls(exec);
2580}
2581
2582// ------------------------------ ThrowNode ------------------------------------
2583
2584void ThrowNode::ref()
2585{
2586 Node::ref();
2587 if ( expr )
2588 expr->ref();
2589}
2590
2591bool ThrowNode::deref()
2592{
2593 if ( expr && expr->deref() )
2594 delete expr;
2595 return Node::deref();
2596}
2597
2598// ECMA 12.13
2599Completion ThrowNode::execute(ExecState *exec)
2600{
2601 KJS_BREAKPOINT;
2602
2603 Value v = expr->evaluate(exec);
2604 KJS_CHECKEXCEPTION
2605
2606 return Completion(Throw, v);
2607}
2608
2609// ------------------------------ CatchNode ------------------------------------
2610
2611void CatchNode::ref()
2612{
2613 Node::ref();
2614 if ( block )
2615 block->ref();
2616}
2617
2618bool CatchNode::deref()
2619{
2620 if ( block && block->deref() )
2621 delete block;
2622 return Node::deref();
2623}
2624
2625Completion CatchNode::execute(ExecState */*exec*/)
2626{
2627 // should never be reached. execute(exec, arg) is used instead
2628 assert(0L);
2629 return Completion();
2630}
2631
2632// ECMA 12.14
2633Completion CatchNode::execute(ExecState *exec, const Value &arg)
2634{
2635 /* TODO: correct ? Not part of the spec */
2636
2637 exec->clearException();
2638
2639 Object obj(new ObjectImp());
2640 obj.put(exec, ident, arg, DontDelete);
2641 exec->context().imp()->pushScope(obj);
2642 Completion c = block->execute(exec);
2643 exec->context().imp()->popScope();
2644
2645 return c;
2646}
2647
2648void CatchNode::processVarDecls(ExecState *exec)
2649{
2650 block->processVarDecls(exec);
2651}
2652
2653// ------------------------------ FinallyNode ----------------------------------
2654
2655void FinallyNode::ref()
2656{
2657 Node::ref();
2658 if ( block )
2659 block->ref();
2660}
2661
2662bool FinallyNode::deref()
2663{
2664 if ( block && block->deref() )
2665 delete block;
2666 return Node::deref();
2667}
2668
2669// ECMA 12.14
2670Completion FinallyNode::execute(ExecState *exec)
2671{
2672 return block->execute(exec);
2673}
2674
2675void FinallyNode::processVarDecls(ExecState *exec)
2676{
2677 block->processVarDecls(exec);
2678}
2679
2680// ------------------------------ TryNode --------------------------------------
2681
2682void TryNode::ref()
2683{
2684 Node::ref();
2685 if ( block )
2686 block->ref();
2687 if ( _final )
2688 _final->ref();
2689 if ( _catch )
2690 _catch->ref();
2691}
2692
2693bool TryNode::deref()
2694{
2695 if ( block && block->deref() )
2696 delete block;
2697 if ( _final && _final->deref() )
2698 delete _final;
2699 if ( _catch && _catch->deref() )
2700 delete _catch;
2701 return Node::deref();
2702}
2703
2704// ECMA 12.14
2705Completion TryNode::execute(ExecState *exec)
2706{
2707 KJS_BREAKPOINT;
2708
2709 Completion c, c2;
2710
2711 c = block->execute(exec);
2712
2713 if (!_final) {
2714 if (c.complType() != Throw)
2715 return c;
2716 return _catch->execute(exec,c.value());
2717 }
2718
2719 if (!_catch) {
2720 Value lastException = exec->exception();
2721 exec->clearException();
2722
2723 c2 = _final->execute(exec);
2724
2725 if (!exec->hadException())
2726 exec->setException(lastException);
2727
2728 return (c2.complType() == Normal) ? c : c2;
2729 }
2730
2731 if (c.complType() == Throw)
2732 c = _catch->execute(exec,c.value());
2733
2734 c2 = _final->execute(exec);
2735 return (c2.complType() == Normal) ? c : c2;
2736}
2737
2738void TryNode::processVarDecls(ExecState *exec)
2739{
2740 block->processVarDecls(exec);
2741 if (_final)
2742 _final->processVarDecls(exec);
2743 if (_catch)
2744 _catch->processVarDecls(exec);
2745}
2746
2747// ------------------------------ ParameterNode --------------------------------
2748
2749void ParameterNode::ref()
2750{
2751 for (ParameterNode *n = this; n; n = n->next)
2752 n->Node::ref();
2753}
2754
2755bool ParameterNode::deref()
2756{
2757 ParameterNode *next;
2758 for (ParameterNode *n = this; n; n = next) {
2759 next = n->next;
2760 if (n != this && n->Node::deref())
2761 delete n;
2762 }
2763 return Node::deref();
2764}
2765
2766// ECMA 13
2767Value ParameterNode::evaluate(ExecState */*exec*/)
2768{
2769 return Undefined();
2770}
2771
2772// ------------------------------ FunctionBodyNode -----------------------------
2773
2774FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2775 : BlockNode(s)
2776{
2777 setLoc(-1, -1, -1);
2778 //fprintf(stderr,"FunctionBodyNode::FunctionBodyNode %p\n",this);
2779}
2780
2781void FunctionBodyNode::processFuncDecl(ExecState *exec)
2782{
2783 if (source)
2784 source->processFuncDecl(exec);
2785}
2786
2787// ------------------------------ FuncDeclNode ---------------------------------
2788
2789void FuncDeclNode::ref()
2790{
2791 Node::ref();
2792 if ( param )
2793 param->ref();
2794 if ( body )
2795 body->ref();
2796}
2797
2798bool FuncDeclNode::deref()
2799{
2800 if ( param && param->deref() )
2801 delete param;
2802 if ( body && body->deref() )
2803 delete body;
2804 return Node::deref();
2805}
2806
2807// ECMA 13
2808void FuncDeclNode::processFuncDecl(ExecState *exec)
2809{
2810 // TODO: let this be an object with [[Class]] property "Function"
2811 FunctionImp *fimp = new DeclaredFunctionImp(exec, ident, body, exec->context().imp()->scopeChain());
2812 Object func(fimp); // protect from GC
2813
2814 // Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,List::empty());
2815 List empty;
2816 Object proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty);
2817 proto.put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2818 func.put(exec, prototypePropertyName, proto, Internal|DontDelete);
2819
2820 int plen = 0;
2821 for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2822 fimp->addParameter(p->ident());
2823
2824 func.put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum);
2825
2826 if (exec->context().imp()->codeType() == EvalCode) {
2827 // ECMA 10.2.2
2828 exec->context().imp()->variableObject().put(exec, ident, func, Internal);
2829 } else {
2830 exec->context().imp()->variableObject().put(exec, ident, func, Internal | DontDelete);
2831 }
2832
2833 if (body) {
2834 // hack the scope so that the function gets put as a property of func, and it's scope
2835 // contains the func as well as our current scope
2836 Object oldVar = exec->context().imp()->variableObject();
2837 exec->context().imp()->setVariableObject(func);
2838 exec->context().imp()->pushScope(func);
2839 body->processFuncDecl(exec);
2840 exec->context().imp()->popScope();
2841 exec->context().imp()->setVariableObject(oldVar);
2842 }
2843}
2844
2845// ------------------------------ FuncExprNode ---------------------------------
2846
2847void FuncExprNode::ref()
2848{
2849 Node::ref();
2850 if ( param )
2851 param->ref();
2852 if ( body )
2853 body->ref();
2854}
2855
2856bool FuncExprNode::deref()
2857{
2858 if ( param && param->deref() )
2859 delete param;
2860 if ( body && body->deref() )
2861 delete body;
2862 return Node::deref();
2863}
2864
2865
2866// ECMA 13
2867Value FuncExprNode::evaluate(ExecState *exec)
2868{
2869 FunctionImp *fimp = new DeclaredFunctionImp(exec, Identifier::null(), body, exec->context().imp()->scopeChain());
2870 Value ret(fimp);
2871 List empty;
2872 Value proto = exec->lexicalInterpreter()->builtinObject().construct(exec,empty);
2873 fimp->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2874
2875 int plen = 0;
2876 for(ParameterNode *p = param; p != 0L; p = p->nextParam(), plen++)
2877 fimp->addParameter(p->ident());
2878
2879 return ret;
2880}
2881
2882// ------------------------------ SourceElementsNode ---------------------------
2883
2884SourceElementsNode::SourceElementsNode(StatementNode *s1)
2885 : element(s1), elements(this)
2886{
2887 setLoc(s1->firstLine(), s1->lastLine(), s1->sourceId());
2888}
2889
2890SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
2891 : element(s2), elements(s1->elements)
2892{
2893 s1->elements = this;
2894 setLoc(s1->firstLine(), s2->lastLine(), s1->sourceId());
2895}
2896
2897void SourceElementsNode::ref()
2898{
2899 for (SourceElementsNode *n = this; n; n = n->elements) {
2900 n->Node::ref();
2901 if (n->element)
2902 n->element->ref();
2903 }
2904}
2905
2906bool SourceElementsNode::deref()
2907{
2908 SourceElementsNode *next;
2909 for (SourceElementsNode *n = this; n; n = next) {
2910 next = n->elements;
2911 if (n->element && n->element->deref())
2912 delete n->element;
2913 if (n != this && n->Node::deref())
2914 delete n;
2915 }
2916 return Node::deref();
2917}
2918
2919// ECMA 14
2920Completion SourceElementsNode::execute(ExecState *exec)
2921{
2922 KJS_CHECKEXCEPTION
2923
2924 Completion c1 = element->execute(exec);
2925 KJS_CHECKEXCEPTION;
2926 if (c1.complType() != Normal)
2927 return c1;
2928
2929 for (SourceElementsNode *n = elements; n; n = n->elements) {
2930 Completion c2 = n->element->execute(exec);
2931 if (c2.complType() != Normal)
2932 return c2;
2933 // The spec says to return c2 here, but it seems that mozilla returns c1 if
2934 // c2 doesn't have a value
2935 if (!c2.value().isNull())
2936 c1 = c2;
2937 }
2938
2939 return c1;
2940}
2941
2942// ECMA 14
2943void SourceElementsNode::processFuncDecl(ExecState *exec)
2944{
2945 for (SourceElementsNode *n = this; n; n = n->elements)
2946 n->element->processFuncDecl(exec);
2947}
2948
2949void SourceElementsNode::processVarDecls(ExecState *exec)
2950{
2951 for (SourceElementsNode *n = this; n; n = n->elements)
2952 n->element->processVarDecls(exec);
2953}
2954
2955ProgramNode::ProgramNode(SourceElementsNode *s): FunctionBodyNode(s) {
2956 //fprintf(stderr,"ProgramNode::ProgramNode %p\n",this);
2957}
Note: See TracBrowser for help on using the repository browser.