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

Last change on this file since 13821 was 13821, checked in by darin, 19 years ago

JavaScriptCore:

Rubber-stamped by John Sullivan.

  • switched from a shell script to a makefile for generated files
  • removed lots of unneeded includes
  • added new Forward.h and HashForward.h headers that allow compiling with fewer unneeded templates
  • DerivedSources.make: Added.
  • generate-derived-sources: Removed.
  • JavaScriptCore.xcodeproj/project.pbxproj: Added new files, changed to use DerivedSources.make.
  • kxmlcore/Forward.h: Added.
  • kxmlcore/HashForward.h: Added.
  • kxmlcore/HashCountedSet.h: Include HashForward for default args.
  • kxmlcore/HashMap.h: Ditto.
  • kxmlcore/HashSet.h: Ditto.
  • kjs/object.h:
  • kjs/object.cpp: Moved KJS_MAX_STACK into the .cpp file.
  • bindings/NP_jsobject.cpp:
  • bindings/c/c_instance.h:
  • bindings/jni/jni_class.h:
  • bindings/jni/jni_runtime.h:
  • bindings/jni/jni_utility.h:
  • bindings/objc/WebScriptObject.mm:
  • bindings/objc/WebScriptObjectPrivate.h:
  • bindings/objc/objc_class.h:
  • bindings/objc/objc_class.mm:
  • bindings/objc/objc_instance.h:
  • bindings/objc/objc_instance.mm:
  • bindings/objc/objc_runtime.mm:
  • bindings/objc/objc_utility.mm:
  • bindings/runtime.h:
  • bindings/runtime_array.cpp:
  • bindings/runtime_array.h:
  • bindings/runtime_method.cpp:
  • bindings/runtime_method.h:
  • bindings/runtime_object.cpp:
  • bindings/runtime_root.h:
  • kjs/JSImmediate.cpp:
  • kjs/Parser.h:
  • kjs/array_object.cpp:
  • kjs/array_object.h:
  • kjs/bool_object.cpp:
  • kjs/bool_object.h:
  • kjs/collector.h:
  • kjs/context.h:
  • kjs/debugger.cpp:
  • kjs/error_object.h:
  • kjs/function_object.h:
  • kjs/internal.h:
  • kjs/lexer.cpp:
  • kjs/math_object.cpp:
  • kjs/math_object.h:
  • kjs/nodes.cpp:
  • kjs/nodes.h:
  • kjs/number_object.cpp:
  • kjs/number_object.h:
  • kjs/object_object.cpp:
  • kjs/operations.cpp:
  • kjs/protected_reference.h:
  • kjs/reference.h:
  • kjs/reference_list.h:
  • kjs/regexp_object.h:
  • kjs/string_object.cpp:
  • kjs/string_object.h:
  • kjs/testkjs.cpp:
  • kjs/value.cpp:
  • kjs/value.h:
  • kxmlcore/HashTable.h:
  • kxmlcore/ListRefPtr.h:
  • kxmlcore/TCPageMap.h:
  • kxmlcore/Vector.h: Removed unneeded header includes.

JavaScriptGlue:

Rubber-stamped by John Sullivan.

  • added forwarding headers for the new Forward.h and HashForward.h files
  • kxmlcore/Forward.h: Added.
  • kxmlcore/HashForward.h: Added.

WebCore:

Rubber-stamped by John Sullivan (except for pbxproj change).

  • updated to use the new Forward.h and HashForward.h headers
  • moved the showTree debugging functions out of the WebCore namespace so they are easier to call from gdb, and renamed the showTree member functions so they don't get in the way; now you can do "call showTree(x)" in gdb and it just works
  • removed a lot of unneeded includes
  • WebCore.xcodeproj/project.pbxproj: Fixed a lot of paths that were not relative to the enclosing group.
  • ForwardingHeaders/kxmlcore/Forward.h: Added.
  • ForwardingHeaders/kxmlcore/HashForward.h: Added.
  • bindings/js/JSCanvasRenderingContext2DBase.cpp:
  • bindings/js/JSXMLHttpRequest.cpp:
  • bindings/js/JSXMLHttpRequest.h:
  • bindings/js/JSXSLTProcessor.h:
  • bindings/js/kjs_binding.h:
  • bindings/js/kjs_dom.cpp:
  • bindings/js/kjs_dom.h:
  • bindings/js/kjs_events.cpp:
  • bindings/js/kjs_events.h:
  • bindings/js/kjs_html.cpp:
  • bindings/js/kjs_navigator.cpp:
  • bindings/js/kjs_navigator.h:
  • bindings/js/kjs_proxy.cpp:
  • bindings/js/kjs_traversal.h:
  • bindings/js/kjs_window.cpp:
  • bindings/js/kjs_window.h:
  • bindings/objc/DOM.mm:
  • bindings/objc/DOMCSS.mm:
  • bindings/objc/DOMCore.h:
  • bindings/objc/DOMEvents.mm:
  • bindings/objc/DOMHTML.mm:
  • bindings/objc/DOMImplementationFront.h:
  • bindings/objc/DOMInternal.mm:
  • bindings/objc/DOMUtility.mm:
  • bindings/objc/DOMViews.mm:
  • bridge/BrowserExtension.h:
  • bridge/mac/BrowserExtensionMac.mm:
  • bridge/mac/FrameMac.h:
  • bridge/mac/FrameMac.mm:
  • bridge/mac/WebCoreFrameBridge.mm:
  • bridge/mac/WebCoreFrameNamespaces.mm:
  • bridge/mac/WebCoreJavaScript.mm:
  • bridge/win/PageWin.cpp:
  • css/CSSComputedStyleDeclaration.cpp:
  • css/css_base.h:
  • css/css_ruleimpl.h:
  • css/css_valueimpl.cpp:
  • css/cssparser.cpp:
  • css/cssparser.h:
  • css/cssstyleselector.cpp:
  • css/cssstyleselector.h:
  • dom/AbstractView.h:
  • dom/AtomicStringList.h:
  • dom/Attribute.cpp:
  • dom/Attribute.h:
  • dom/Comment.cpp:
  • dom/ContainerNode.cpp:
  • dom/DOMImplementation.cpp:
  • dom/DOMImplementation.h:
  • dom/Document.cpp:
  • dom/Document.h:
  • dom/Element.h:
  • dom/EventTargetNode.cpp: (WebCore::EventTargetNode::dump): (WebCore::forbidEventDispatch): (WebCore::allowEventDispatch): (WebCore::eventDispatchForbidden):
  • dom/EventTargetNode.h: (WebCore::EventTargetNode::postDispatchEventHandler):
  • dom/NamedAttrMap.h:
  • dom/Node.cpp: (WebCore::Node::showNode): (WebCore::Node::showTree): (WebCore::Node::showTreeAndMark): (showTree):
  • dom/Node.h:
  • dom/NodeList.cpp:
  • dom/NodeList.h:
  • dom/Position.cpp: (showTree):
  • dom/Position.h:
  • dom/Range.cpp:
  • dom/Range.h:
  • dom/StyledElement.cpp:
  • dom/StyledElement.h:
  • dom/dom2_eventsimpl.cpp:
  • dom/dom2_eventsimpl.h:
  • dom/dom2_traversalimpl.h:
  • dom/dom_xmlimpl.cpp:
  • dom/xml_tokenizer.cpp:
  • dom/xml_tokenizer.h:
  • editing/AppendNodeCommand.cpp:
  • editing/ApplyStyleCommand.cpp:
  • editing/ApplyStyleCommand.h:
  • editing/BreakBlockquoteCommand.cpp:
  • editing/CompositeEditCommand.cpp:
  • editing/CreateLinkCommand.cpp:
  • editing/DeleteFromTextNodeCommand.cpp:
  • editing/DeleteFromTextNodeCommand.h:
  • editing/DeleteSelectionCommand.cpp:
  • editing/EditCommand.cpp:
  • editing/EditCommand.h:
  • editing/HTMLInterchange.cpp:
  • editing/InsertIntoTextNodeCommand.cpp:
  • editing/InsertIntoTextNodeCommand.h:
  • editing/InsertLineBreakCommand.cpp:
  • editing/InsertNodeBeforeCommand.cpp:
  • editing/InsertParagraphSeparatorCommand.cpp:
  • editing/InsertTextCommand.cpp:
  • editing/JSEditor.cpp:
  • editing/JoinTextNodesCommand.cpp:
  • editing/MergeIdenticalElementsCommand.cpp:
  • editing/ModifySelectionListLevelCommand.cpp:
  • editing/MoveSelectionCommand.cpp:
  • editing/RebalanceWhitespaceCommand.h:
  • editing/RemoveCSSPropertyCommand.h:
  • editing/ReplaceSelectionCommand.cpp:
  • editing/ReplaceSelectionCommand.h:
  • editing/Selection.cpp: (WebCore::Selection::formatForDebugger): (WebCore::Selection::showTree): (showTree):
  • editing/Selection.h:
  • editing/SelectionController.cpp: (WebCore::SelectionController::formatForDebugger): (WebCore::SelectionController::showTree): (showTree):
  • editing/SelectionController.h:
  • editing/TextIterator.cpp:
  • editing/TextIterator.h:
  • editing/TypingCommand.cpp:
  • editing/TypingCommand.h:
  • editing/UnlinkCommand.cpp:
  • editing/VisiblePosition.cpp: (WebCore::isEqualIgnoringAffinity): (WebCore::VisiblePosition::formatForDebugger): (WebCore::VisiblePosition::showTree): (showTree):
  • editing/VisiblePosition.h: (WebCore::VisiblePosition::VisiblePosition): (WebCore::operator==):
  • editing/WrapContentsInDummySpanCommand.cpp:
  • editing/htmlediting.h:
  • editing/markup.cpp:
  • editing/markup.h: (WebCore::):
  • editing/visible_units.cpp:
  • html/CanvasGradient.cpp:
  • html/CanvasRenderingContext2D.h:
  • html/CanvasStyle.cpp:
  • html/CanvasStyle.h:
  • html/FormDataList.cpp:
  • html/FormDataList.h:
  • html/HTMLCollection.cpp:
  • html/HTMLCollection.h:
  • html/HTMLDocument.cpp:
  • html/HTMLDocument.h:
  • html/HTMLElement.cpp:
  • html/HTMLElementFactory.cpp:
  • html/HTMLElementFactory.h:
  • html/HTMLFormCollection.cpp:
  • html/HTMLFormElement.cpp:
  • html/HTMLFormElement.h:
  • html/HTMLInputElement.cpp:
  • html/HTMLParser.cpp:
  • html/HTMLSelectElement.cpp:
  • html/HTMLSelectElement.h:
  • html/HTMLTokenizer.cpp:
  • html/HTMLTokenizer.h:
  • html/html_baseimpl.cpp:
  • html/html_headimpl.h:
  • kcanvas/KCanvasCreator.cpp:
  • kcanvas/KCanvasFilters.h:
  • kcanvas/KCanvasPath.h:
  • kcanvas/KCanvasResources.h:
  • kcanvas/KCanvasTreeDebug.cpp:
  • kcanvas/RenderPath.cpp:
  • kcanvas/RenderPath.h:
  • kcanvas/device/KRenderingDevice.h:
  • kcanvas/device/KRenderingPaintServerGradient.h:
  • kcanvas/device/KRenderingPaintServerPattern.h:
  • kcanvas/device/KRenderingPaintServerSolid.h:
  • kcanvas/device/quartz/KCanvasFilterQuartz.mm:
  • kcanvas/device/quartz/KCanvasMaskerQuartz.h:
  • kcanvas/device/quartz/KCanvasResourcesQuartz.h:
  • kcanvas/device/quartz/KCanvasResourcesQuartz.mm:
  • kcanvas/device/quartz/KRenderingPaintServerQuartz.h:
  • khtml/misc/decoder.cpp:
  • khtml/misc/decoder.h:
  • khtml/xsl/XSLStyleSheet.cpp:
  • khtml/xsl/XSLTProcessor.cpp:
  • khtml/xsl/XSLTProcessor.h:
  • ksvg2/css/SVGRenderStyle.h:
  • ksvg2/ecma/GlobalObject.cpp:
  • ksvg2/misc/KCanvasRenderingStyle.h:
  • ksvg2/misc/SVGDocumentExtensions.h:
  • ksvg2/svg/SVGAngle.h:
  • ksvg2/svg/SVGAnimateColorElement.h:
  • ksvg2/svg/SVGAnimatedColor.h:
  • ksvg2/svg/SVGAnimatedLengthList.h:
  • ksvg2/svg/SVGAnimatedNumberList.h:
  • ksvg2/svg/SVGAnimatedString.h:
  • ksvg2/svg/SVGAnimatedTransformList.h:
  • ksvg2/svg/SVGAnimationElement.h:
  • ksvg2/svg/SVGColor.h:
  • ksvg2/svg/SVGCursorElement.h:
  • ksvg2/svg/SVGHelper.h:
  • ksvg2/svg/SVGLength.h:
  • ksvg2/svg/SVGList.h:
  • ksvg2/svg/SVGPaint.h:
  • ksvg2/svg/SVGPathSeg.h:
  • ksvg2/svg/SVGPatternElement.h:
  • ksvg2/svg/SVGSVGElement.cpp:
  • ksvg2/svg/SVGSVGElement.h:
  • ksvg2/svg/SVGStringList.h:
  • ksvg2/svg/SVGTransform.h:
  • kwq/AccessibilityObjectCache.mm:
  • kwq/ClipboardMac.mm:
  • kwq/JavaAppletWidget.mm:
  • kwq/KWQComboBox.mm:
  • kwq/KWQEditCommand.mm:
  • kwq/KWQFileButton.mm:
  • kwq/KWQKHTMLSettings.h:
  • kwq/KWQKSSLKeyGen.mm:
  • kwq/KWQLoader.mm:
  • kwq/KWQPageState.mm:
  • kwq/KWQTextEdit.mm:
  • kwq/RegularExpression.h:
  • kwq/RenderTreeAsText.cpp:
  • kwq/RenderTreeAsText.h:
  • kwq/WebCoreAXObject.mm:
  • loader/Cache.cpp:
  • loader/Cache.h:
  • loader/CachedCSSStyleSheet.cpp:
  • loader/CachedObject.h:
  • loader/CachedScript.cpp:
  • loader/CachedXBLDocument.cpp:
  • loader/CachedXBLDocument.h:
  • loader/CachedXSLStyleSheet.cpp:
  • loader/CachedXSLStyleSheet.h:
  • loader/DocLoader.cpp:
  • page/Frame.cpp:
  • page/Frame.h:
  • page/FramePrivate.h:
  • page/FrameTree.cpp:
  • page/FrameTree.h:
  • page/FrameView.cpp:
  • page/FrameView.h:
  • page/Page.cpp:
  • page/Page.h:
  • page/Plugin.h: (WebCore::Plugin::Plugin): (WebCore::Plugin::view):
  • platform/Color.cpp:
  • platform/FloatRect.h:
  • platform/Font.cpp:
  • platform/Font.h:
  • platform/FontFamily.cpp:
  • platform/GraphicsContext.cpp:
  • platform/Image.cpp:
  • platform/Image.h:
  • platform/IntRect.h:
  • platform/KURL.cpp:
  • platform/KURL.h:
  • platform/SegmentedString.h:
  • platform/Shared.h:
  • platform/StreamingTextDecoder.cpp:
  • platform/StringImpl.cpp:
  • platform/StringImpl.h:
  • platform/TextEncoding.h:
  • platform/Timer.cpp:
  • platform/Timer.h:
  • platform/TransferJob.cpp:
  • platform/TransferJob.h:
  • platform/TransferJobInternal.h:
  • platform/cairo/GraphicsContextCairo.cpp:
  • platform/cairo/ImageCairo.cpp:
  • platform/cairo/ImageSourceCairo.cpp:
  • platform/image-decoders/gif/GIFImageReader.cpp:
  • platform/image-decoders/jpeg/JPEGImageDecoder.cpp:
  • platform/mac/FontFamilyMac.mm:
  • platform/mac/FontMac.mm:
  • platform/mac/ImageMac.mm:
  • platform/mac/TextEncodingMac.cpp:
  • platform/mac/TransferJobMac.mm:
  • platform/win/FontPlatformDataWin.cpp:
  • platform/win/TransferJobWin.cpp:
  • rendering/RenderBlock.cpp:
  • rendering/RenderBlock.h:
  • rendering/RenderBox.cpp:
  • rendering/RenderBox.h:
  • rendering/RenderCanvas.cpp:
  • rendering/RenderCanvas.h:
  • rendering/RenderContainer.cpp:
  • rendering/RenderFlexibleBox.h:
  • rendering/RenderFlow.cpp:
  • rendering/RenderFlow.h:
  • rendering/RenderImage.cpp:
  • rendering/RenderImage.h:
  • rendering/RenderLayer.cpp:
  • rendering/RenderLayer.h:
  • rendering/RenderObject.cpp: (showTree):
  • rendering/RenderObject.h:
  • rendering/RenderTableCell.h:
  • rendering/RenderTableSection.h:
  • rendering/RenderText.cpp:
  • rendering/RenderText.h:
  • rendering/RenderTextField.cpp:
  • rendering/RenderTextFragment.h:
  • rendering/RenderTheme.h:
  • rendering/RenderThemeMac.mm:
  • rendering/RenderThemeWin.cpp:
  • rendering/bidi.cpp:
  • rendering/render_form.h:
  • rendering/render_line.cpp: (showTree):
  • rendering/render_line.h:
  • rendering/render_list.cpp:
  • rendering/render_replaced.cpp:
  • rendering/render_replaced.h:
  • rendering/render_style.cpp:
  • rendering/render_style.h:
  • xml/xmlhttprequest.h:
  • Property allow-tabs set to x
  • Property svn:eol-style set to native
File size: 63.4 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2002 Harri Porten ([email protected])
4 * Copyright (C) 2001 Peter Kelly ([email protected])
5 * Copyright (C) 2003 Apple Computer, Inc.
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
11 *
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
16 *
17 * You should have received a copy of the GNU Library General Public License
18 * along with this library; see the file COPYING.LIB. If not, write to
19 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 * Boston, MA 02110-1301, USA.
21 *
22 */
23
24#include "config.h"
25#include "nodes.h"
26
27#include <math.h>
28#ifdef KJS_DEBUG_MEM
29#include <stdio.h>
30#include <typeinfo>
31#endif
32
33#include "context.h"
34#include "debugger.h"
35#include "function_object.h"
36#include "lexer.h"
37#include "operations.h"
38#include "reference_list.h"
39#include <kxmlcore/HashSet.h>
40#include <kxmlcore/HashCountedSet.h>
41
42using namespace KJS;
43
44#define KJS_BREAKPOINT \
45 if (Debugger::debuggersPresent > 0 && !hitStatement(exec)) \
46 return Completion(Normal);
47
48#define KJS_ABORTPOINT \
49 if (Debugger::debuggersPresent > 0 && \
50 exec->dynamicInterpreter()->imp()->debugger() && \
51 exec->dynamicInterpreter()->imp()->debugger()->imp()->aborted()) \
52 return Completion(Normal);
53
54#define KJS_CHECKEXCEPTION \
55 if (exec->hadException()) { \
56 setExceptionDetailsIfNeeded(exec); \
57 JSValue *ex = exec->exception(); \
58 exec->clearException(); \
59 return Completion(Throw, ex); \
60 } \
61 if (Collector::isOutOfMemory()) \
62 return Completion(Throw, Error::create(exec, GeneralError, "Out of memory"));
63
64#define KJS_CHECKEXCEPTIONVALUE \
65 if (exec->hadException()) { \
66 setExceptionDetailsIfNeeded(exec); \
67 return jsUndefined(); \
68 } \
69 if (Collector::isOutOfMemory()) \
70 return jsUndefined(); // will be picked up by KJS_CHECKEXCEPTION
71
72#define KJS_CHECKEXCEPTIONLIST \
73 if (exec->hadException()) { \
74 setExceptionDetailsIfNeeded(exec); \
75 return List(); \
76 } \
77 if (Collector::isOutOfMemory()) \
78 return List(); // will be picked up by KJS_CHECKEXCEPTION
79
80// ------------------------------ Node -----------------------------------------
81
82
83#ifndef NDEBUG
84struct NodeCounter {
85 static int count;
86 ~NodeCounter() { if (count != 0) fprintf(stderr, "LEAK: %d KJS::Node\n", count); }
87};
88int NodeCounter::count = 0;
89static NodeCounter nodeImplCounter;
90#endif NDEBUG
91
92static HashSet<Node*>* newNodes;
93static HashCountedSet<Node*>* nodeExtraRefCounts;
94
95Node::Node()
96{
97#ifndef NDEBUG
98 ++NodeCounter::count;
99#endif
100 m_line = Lexer::curr()->lineNo();
101 if (!newNodes)
102 newNodes = new HashSet<Node*>;
103 newNodes->add(this);
104}
105
106Node::~Node()
107{
108#ifndef NDEBUG
109 --NodeCounter::count;
110#endif
111}
112
113void Node::ref()
114{
115 // bumping from 0 to 1 is just removing from the new nodes set
116 if (newNodes) {
117 HashSet<Node*>::iterator it = newNodes->find(this);
118 if (it != newNodes->end()) {
119 newNodes->remove(it);
120 ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
121 return;
122 }
123 }
124
125 ASSERT(!newNodes || !newNodes->contains(this));
126
127 if (!nodeExtraRefCounts)
128 nodeExtraRefCounts = new HashCountedSet<Node*>;
129 nodeExtraRefCounts->add(this);
130}
131
132void Node::deref()
133{
134 ASSERT(!newNodes || !newNodes->contains(this));
135
136 if (!nodeExtraRefCounts) {
137 delete this;
138 return;
139 }
140
141 HashCountedSet<Node*>::iterator it = nodeExtraRefCounts->find(this);
142 if (it == nodeExtraRefCounts->end())
143 delete this;
144 else
145 nodeExtraRefCounts->remove(it);
146}
147
148unsigned Node::refcount()
149{
150 if (newNodes && newNodes->contains(this)) {
151 ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
152 return 0;
153 }
154
155 ASSERT(!newNodes || !newNodes->contains(this));
156
157 if (!nodeExtraRefCounts)
158 return 1;
159
160 return 1 + nodeExtraRefCounts->count(this);
161}
162
163void Node::clearNewNodes()
164{
165 if (!newNodes)
166 return;
167
168#ifndef NDEBUG
169 HashSet<Node*>::iterator end = newNodes->end();
170 for (HashSet<Node*>::iterator it = newNodes->begin(); it != end; ++it)
171 ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(*it));
172#endif
173 deleteAllValues(*newNodes);
174 delete newNodes;
175 newNodes = 0;
176}
177
178static void substitute(UString &string, const UString &substring)
179{
180 int position = string.find("%s");
181 assert(position != -1);
182 string = string.substr(0, position) + substring + string.substr(position + 2);
183}
184
185static inline int currentSourceId(ExecState* exec)
186{
187 return exec->context().imp()->currentBody()->sourceId();
188}
189
190static inline const UString& currentSourceURL(ExecState* exec)
191{
192 return exec->context().imp()->currentBody()->sourceURL();
193}
194
195Completion Node::createErrorCompletion(ExecState* exec, ErrorType e, const char *msg)
196{
197 return Completion(Throw, Error::create(exec, e, msg, lineNo(), currentSourceId(exec), &currentSourceURL(exec)));
198}
199
200Completion Node::createErrorCompletion(ExecState *exec, ErrorType e, const char *msg, const Identifier &ident)
201{
202 UString message = msg;
203 substitute(message, ident.ustring());
204 return Completion(Throw, Error::create(exec, e, message, lineNo(), currentSourceId(exec), &currentSourceURL(exec)));
205}
206
207JSValue *Node::throwError(ExecState* exec, ErrorType e, const char *msg)
208{
209 return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), &currentSourceURL(exec));
210}
211
212JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, JSValue *v, Node *expr)
213{
214 UString message = msg;
215 substitute(message, v->toString(exec));
216 substitute(message, expr->toString());
217 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), &currentSourceURL(exec));
218}
219
220
221JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, const Identifier &label)
222{
223 UString message = msg;
224 substitute(message, label.ustring());
225 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), &currentSourceURL(exec));
226}
227
228JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, JSValue *v, Node *e1, Node *e2)
229{
230 UString message = msg;
231 substitute(message, v->toString(exec));
232 substitute(message, e1->toString());
233 substitute(message, e2->toString());
234 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), &currentSourceURL(exec));
235}
236
237JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, JSValue *v, Node *expr, const Identifier &label)
238{
239 UString message = msg;
240 substitute(message, v->toString(exec));
241 substitute(message, expr->toString());
242 substitute(message, label.ustring());
243 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), &currentSourceURL(exec));
244}
245
246JSValue *Node::throwError(ExecState *exec, ErrorType e, const char *msg, JSValue *v, const Identifier &label)
247{
248 UString message = msg;
249 substitute(message, v->toString(exec));
250 substitute(message, label.ustring());
251 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), &currentSourceURL(exec));
252}
253
254JSValue *Node::throwUndefinedVariableError(ExecState *exec, const Identifier &ident)
255{
256 return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
257}
258
259void Node::setExceptionDetailsIfNeeded(ExecState *exec)
260{
261 JSValue *exceptionValue = exec->exception();
262 if (exceptionValue->isObject()) {
263 JSObject *exception = static_cast<JSObject *>(exceptionValue);
264 if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
265 exception->put(exec, "line", jsNumber(m_line));
266 exception->put(exec, "sourceURL", jsString(currentSourceURL(exec)));
267 }
268 }
269}
270
271Node *Node::nodeInsideAllParens()
272{
273 return this;
274}
275
276// ------------------------------ StatementNode --------------------------------
277
278StatementNode::StatementNode()
279 : m_lastLine(-1)
280{
281 m_line = -1;
282}
283
284void StatementNode::setLoc(int firstLine, int lastLine)
285{
286 m_line = firstLine;
287 m_lastLine = lastLine;
288}
289
290// return true if the debugger wants us to stop at this point
291bool StatementNode::hitStatement(ExecState* exec)
292{
293 Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
294 if (dbg)
295 return dbg->atStatement(exec, currentSourceId(exec), firstLine(), lastLine());
296 else
297 return true; // continue
298}
299
300void StatementNode::processFuncDecl(ExecState*)
301{
302}
303
304// ------------------------------ NullNode -------------------------------------
305
306JSValue *NullNode::evaluate(ExecState *)
307{
308 return jsNull();
309}
310
311// ------------------------------ BooleanNode ----------------------------------
312
313JSValue *BooleanNode::evaluate(ExecState *)
314{
315 return jsBoolean(value);
316}
317
318// ------------------------------ NumberNode -----------------------------------
319
320JSValue *NumberNode::evaluate(ExecState *)
321{
322 return jsNumber(value);
323}
324
325// ------------------------------ StringNode -----------------------------------
326
327JSValue *StringNode::evaluate(ExecState *)
328{
329 return jsString(value);
330}
331
332// ------------------------------ RegExpNode -----------------------------------
333
334JSValue *RegExpNode::evaluate(ExecState *exec)
335{
336 List list;
337 list.append(jsString(pattern));
338 list.append(jsString(flags));
339
340 JSObject *reg = exec->lexicalInterpreter()->imp()->builtinRegExp();
341 return reg->construct(exec,list);
342}
343
344// ------------------------------ ThisNode -------------------------------------
345
346// ECMA 11.1.1
347JSValue *ThisNode::evaluate(ExecState *exec)
348{
349 return exec->context().imp()->thisValue();
350}
351
352// ------------------------------ ResolveNode ----------------------------------
353
354// ECMA 11.1.2 & 10.1.4
355JSValue *ResolveNode::evaluate(ExecState *exec)
356{
357 const ScopeChain& chain = exec->context().imp()->scopeChain();
358 ScopeChainIterator iter = chain.begin();
359 ScopeChainIterator end = chain.end();
360
361 // we must always have something in the scope chain
362 assert(iter != end);
363
364 PropertySlot slot;
365 do {
366 JSObject *o = *iter;
367
368 if (o->getPropertySlot(exec, ident, slot))
369 return slot.getValue(exec, o, ident);
370
371 ++iter;
372 } while (iter != end);
373
374 return throwUndefinedVariableError(exec, ident);
375}
376
377// ------------------------------ GroupNode ------------------------------------
378
379// ECMA 11.1.6
380JSValue *GroupNode::evaluate(ExecState *exec)
381{
382 return group->evaluate(exec);
383}
384
385Node *GroupNode::nodeInsideAllParens()
386{
387 Node *n = this;
388 do
389 n = static_cast<GroupNode *>(n)->group.get();
390 while (n->isGroupNode());
391 return n;
392}
393
394// ------------------------------ ElementNode ----------------------------------
395
396// ECMA 11.1.4
397JSValue *ElementNode::evaluate(ExecState *exec)
398{
399 JSObject *array = exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty());
400 int length = 0;
401 for (ElementNode *n = this; n; n = n->next.get()) {
402 JSValue *val = n->node->evaluate(exec);
403 KJS_CHECKEXCEPTIONVALUE
404 length += n->elision;
405 array->put(exec, length++, val);
406 }
407 return array;
408}
409
410void ElementNode::breakCycle()
411{
412 next = 0;
413}
414
415// ------------------------------ ArrayNode ------------------------------------
416
417// ECMA 11.1.4
418JSValue *ArrayNode::evaluate(ExecState *exec)
419{
420 JSObject *array;
421 int length;
422
423 if (element) {
424 array = static_cast<JSObject*>(element->evaluate(exec));
425 KJS_CHECKEXCEPTIONVALUE
426 length = opt ? array->get(exec,lengthPropertyName)->toInt32(exec) : 0;
427 } else {
428 JSValue *newArr = exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty());
429 array = static_cast<JSObject*>(newArr);
430 length = 0;
431 }
432
433 if (opt)
434 array->put(exec,lengthPropertyName, jsNumber(elision + length), DontEnum | DontDelete);
435
436 return array;
437}
438
439// ------------------------------ ObjectLiteralNode ----------------------------
440
441// ECMA 11.1.5
442JSValue *ObjectLiteralNode::evaluate(ExecState *exec)
443{
444 if (list)
445 return list->evaluate(exec);
446
447 return exec->lexicalInterpreter()->builtinObject()->construct(exec,List::empty());
448}
449
450// ------------------------------ PropertyListNode -----------------------------
451
452// ECMA 11.1.5
453JSValue *PropertyListNode::evaluate(ExecState *exec)
454{
455 JSObject *obj = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
456
457 for (PropertyListNode *p = this; p; p = p->next.get()) {
458 JSValue *n = p->node->name->evaluate(exec);
459 KJS_CHECKEXCEPTIONVALUE
460 JSValue *v = p->node->assign->evaluate(exec);
461 KJS_CHECKEXCEPTIONVALUE
462
463 Identifier propertyName = Identifier(n->toString(exec));
464 switch (p->node->type) {
465 case PropertyNode::Getter:
466 assert(v->isObject());
467 obj->defineGetter(exec, propertyName, static_cast<JSObject *>(v));
468 break;
469 case PropertyNode::Setter:
470 assert(v->isObject());
471 obj->defineSetter(exec, propertyName, static_cast<JSObject *>(v));
472 break;
473 case PropertyNode::Constant:
474 obj->put(exec, propertyName, v);
475 break;
476 }
477 }
478
479 return obj;
480}
481
482void PropertyListNode::breakCycle()
483{
484 next = 0;
485}
486
487// ------------------------------ PropertyNode -----------------------------
488// ECMA 11.1.5
489JSValue *PropertyNode::evaluate(ExecState*)
490{
491 assert(false);
492 return jsNull();
493}
494
495// ---------------------------- PropertyNameNode -------------------------------
496
497// ECMA 11.1.5
498JSValue *PropertyNameNode::evaluate(ExecState*)
499{
500 JSValue *s;
501
502 if (str.isNull()) {
503 s = jsString(UString::from(numeric));
504 } else {
505 s = jsString(str.ustring());
506 }
507
508 return s;
509}
510
511// ------------------------------ BracketAccessorNode --------------------------------
512
513// ECMA 11.2.1a
514JSValue *BracketAccessorNode::evaluate(ExecState *exec)
515{
516 JSValue *v1 = expr1->evaluate(exec);
517 KJS_CHECKEXCEPTIONVALUE
518 JSValue *v2 = expr2->evaluate(exec);
519 KJS_CHECKEXCEPTIONVALUE
520 JSObject *o = v1->toObject(exec);
521 uint32_t i;
522 if (v2->getUInt32(i))
523 return o->get(exec, i);
524 return o->get(exec, Identifier(v2->toString(exec)));
525}
526
527// ------------------------------ DotAccessorNode --------------------------------
528
529// ECMA 11.2.1b
530JSValue *DotAccessorNode::evaluate(ExecState *exec)
531{
532 JSValue *v = expr->evaluate(exec);
533 KJS_CHECKEXCEPTIONVALUE
534 return v->toObject(exec)->get(exec, ident);
535
536}
537
538// ------------------------------ ArgumentListNode -----------------------------
539
540JSValue *ArgumentListNode::evaluate(ExecState *)
541{
542 assert(0);
543 return 0; // dummy, see evaluateList()
544}
545
546// ECMA 11.2.4
547List ArgumentListNode::evaluateList(ExecState *exec)
548{
549 List l;
550
551 for (ArgumentListNode *n = this; n; n = n->next.get()) {
552 JSValue *v = n->expr->evaluate(exec);
553 KJS_CHECKEXCEPTIONLIST
554 l.append(v);
555 }
556
557 return l;
558}
559
560void ArgumentListNode::breakCycle()
561{
562 next = 0;
563}
564
565// ------------------------------ ArgumentsNode --------------------------------
566
567JSValue *ArgumentsNode::evaluate(ExecState *)
568{
569 assert(0);
570 return 0; // dummy, see evaluateList()
571}
572
573// ------------------------------ NewExprNode ----------------------------------
574
575// ECMA 11.2.2
576
577JSValue *NewExprNode::evaluate(ExecState *exec)
578{
579 JSValue *v = expr->evaluate(exec);
580 KJS_CHECKEXCEPTIONVALUE
581
582 List argList;
583 if (args) {
584 argList = args->evaluateList(exec);
585 KJS_CHECKEXCEPTIONVALUE
586 }
587
588 if (!v->isObject()) {
589 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, expr.get());
590 }
591
592 JSObject *constr = static_cast<JSObject*>(v);
593 if (!constr->implementsConstruct()) {
594 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr.get());
595 }
596
597 return constr->construct(exec, argList);
598}
599
600// ECMA 11.2.3
601JSValue *FunctionCallValueNode::evaluate(ExecState *exec)
602{
603 JSValue *v = expr->evaluate(exec);
604 KJS_CHECKEXCEPTIONVALUE
605
606 if (!v->isObject()) {
607 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, expr.get());
608 }
609
610 JSObject *func = static_cast<JSObject*>(v);
611
612 if (!func->implementsCall()) {
613 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, expr.get());
614 }
615
616 List argList = args->evaluateList(exec);
617 KJS_CHECKEXCEPTIONVALUE
618
619 JSObject *thisObj = exec->dynamicInterpreter()->globalObject();
620
621 return func->call(exec, thisObj, argList);
622}
623
624// ECMA 11.2.3
625JSValue *FunctionCallResolveNode::evaluate(ExecState *exec)
626{
627 const ScopeChain& chain = exec->context().imp()->scopeChain();
628 ScopeChainIterator iter = chain.begin();
629 ScopeChainIterator end = chain.end();
630
631 // we must always have something in the scope chain
632 assert(iter != end);
633
634 PropertySlot slot;
635 JSObject *base;
636 do {
637 base = *iter;
638 if (base->getPropertySlot(exec, ident, slot)) {
639 JSValue *v = slot.getValue(exec, base, ident);
640 KJS_CHECKEXCEPTIONVALUE
641
642 if (!v->isObject()) {
643 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
644 }
645
646 JSObject *func = static_cast<JSObject*>(v);
647
648 if (!func->implementsCall()) {
649 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
650 }
651
652 List argList = args->evaluateList(exec);
653 KJS_CHECKEXCEPTIONVALUE
654
655 JSObject *thisObj = base;
656 // ECMA 11.2.3 says that in this situation the this value should be null.
657 // However, section 10.2.3 says that in the case where the value provided
658 // by the caller is null, the global object should be used. It also says
659 // that the section does not apply to interal functions, but for simplicity
660 // of implementation we use the global object anyway here. This guarantees
661 // that in host objects you always get a valid object for this.
662 if (thisObj->isActivation())
663 thisObj = exec->dynamicInterpreter()->globalObject();
664
665 return func->call(exec, thisObj, argList);
666 }
667 ++iter;
668 } while (iter != end);
669
670 return throwUndefinedVariableError(exec, ident);
671}
672
673// ECMA 11.2.3
674JSValue *FunctionCallBracketNode::evaluate(ExecState *exec)
675{
676 JSValue *baseVal = base->evaluate(exec);
677 KJS_CHECKEXCEPTIONVALUE
678
679 JSValue *subscriptVal = subscript->evaluate(exec);
680
681 JSObject *baseObj = baseVal->toObject(exec);
682 uint32_t i;
683 PropertySlot slot;
684
685 JSValue *funcVal;
686 if (subscriptVal->getUInt32(i)) {
687 if (baseObj->getPropertySlot(exec, i, slot))
688 funcVal = slot.getValue(exec, baseObj, i);
689 else
690 funcVal = jsUndefined();
691 } else {
692 Identifier ident(subscriptVal->toString(exec));
693 if (baseObj->getPropertySlot(exec, ident, slot))
694 funcVal = baseObj->get(exec, ident);
695 else
696 funcVal = jsUndefined();
697 }
698
699 KJS_CHECKEXCEPTIONVALUE
700
701 if (!funcVal->isObject()) {
702 return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, base.get(), subscript.get());
703 }
704
705 JSObject *func = static_cast<JSObject*>(funcVal);
706
707 if (!func->implementsCall()) {
708 return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, base.get(), subscript.get());
709 }
710
711 List argList = args->evaluateList(exec);
712 KJS_CHECKEXCEPTIONVALUE
713
714 JSObject *thisObj = baseObj;
715 assert(thisObj);
716 assert(thisObj->isObject());
717 assert(!thisObj->isActivation());
718
719 return func->call(exec, thisObj, argList);
720}
721
722static const char *dotExprNotAnObjectString()
723{
724 return "Value %s (result of expression %s.%s) is not object.";
725}
726
727static const char *dotExprDoesNotAllowCallsString()
728{
729 return "Object %s (result of expression %s.%s) does not allow calls.";
730}
731
732// ECMA 11.2.3
733JSValue *FunctionCallDotNode::evaluate(ExecState *exec)
734{
735 JSValue *baseVal = base->evaluate(exec);
736
737 JSObject *baseObj = baseVal->toObject(exec);
738 PropertySlot slot;
739 JSValue *funcVal = baseObj->getPropertySlot(exec, ident, slot) ? slot.getValue(exec, baseObj, ident) : jsUndefined();
740 KJS_CHECKEXCEPTIONVALUE
741
742 if (!funcVal->isObject())
743 return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, base.get(), ident);
744
745 JSObject *func = static_cast<JSObject*>(funcVal);
746
747 if (!func->implementsCall())
748 return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, base.get(), ident);
749
750 List argList = args->evaluateList(exec);
751 KJS_CHECKEXCEPTIONVALUE
752
753 JSObject *thisObj = baseObj;
754 assert(thisObj);
755 assert(thisObj->isObject());
756 assert(!thisObj->isActivation());
757
758 return func->call(exec, thisObj, argList);
759}
760
761// ECMA 11.3
762
763// ------------------------------ PostfixResolveNode ----------------------------------
764
765JSValue *PostfixResolveNode::evaluate(ExecState *exec)
766{
767 const ScopeChain& chain = exec->context().imp()->scopeChain();
768 ScopeChainIterator iter = chain.begin();
769 ScopeChainIterator end = chain.end();
770
771 // we must always have something in the scope chain
772 assert(iter != end);
773
774 PropertySlot slot;
775 JSObject *base;
776 do {
777 base = *iter;
778 if (base->getPropertySlot(exec, m_ident, slot)) {
779 JSValue *v = slot.getValue(exec, base, m_ident);
780
781 double n = v->toNumber(exec);
782
783 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
784 base->put(exec, m_ident, jsNumber(newValue));
785
786 return jsNumber(n);
787 }
788
789 ++iter;
790 } while (iter != end);
791
792 return throwUndefinedVariableError(exec, m_ident);
793}
794
795// ------------------------------ PostfixBracketNode ----------------------------------
796
797JSValue *PostfixBracketNode::evaluate(ExecState *exec)
798{
799 JSValue *baseValue = m_base->evaluate(exec);
800 KJS_CHECKEXCEPTIONVALUE
801 JSValue *subscript = m_subscript->evaluate(exec);
802 KJS_CHECKEXCEPTIONVALUE
803
804 JSObject *base = baseValue->toObject(exec);
805
806 uint32_t propertyIndex;
807 if (subscript->getUInt32(propertyIndex)) {
808 PropertySlot slot;
809 JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
810 KJS_CHECKEXCEPTIONVALUE
811
812 double n = v->toNumber(exec);
813
814 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
815 base->put(exec, propertyIndex, jsNumber(newValue));
816
817 return jsNumber(n);
818 }
819
820 Identifier propertyName(subscript->toString(exec));
821 PropertySlot slot;
822 JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
823 KJS_CHECKEXCEPTIONVALUE
824
825 double n = v->toNumber(exec);
826
827 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
828 base->put(exec, propertyName, jsNumber(newValue));
829
830 return jsNumber(n);
831}
832
833// ------------------------------ PostfixDotNode ----------------------------------
834
835JSValue *PostfixDotNode::evaluate(ExecState *exec)
836{
837 JSValue *baseValue = m_base->evaluate(exec);
838 KJS_CHECKEXCEPTIONVALUE
839 JSObject *base = baseValue->toObject(exec);
840
841 PropertySlot slot;
842 JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
843 KJS_CHECKEXCEPTIONVALUE
844
845 double n = v->toNumber(exec);
846
847 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
848 base->put(exec, m_ident, jsNumber(newValue));
849
850 return jsNumber(n);
851}
852
853// ECMA 11.4.1
854
855// ------------------------------ DeleteResolveNode -----------------------------------
856JSValue *DeleteResolveNode::evaluate(ExecState *exec)
857{
858 const ScopeChain& chain = exec->context().imp()->scopeChain();
859 ScopeChainIterator iter = chain.begin();
860 ScopeChainIterator end = chain.end();
861
862 // we must always have something in the scope chain
863 assert(iter != end);
864
865 PropertySlot slot;
866 JSObject *base;
867 do {
868 base = *iter;
869 if (base->getPropertySlot(exec, m_ident, slot)) {
870 return jsBoolean(base->deleteProperty(exec, m_ident));
871 }
872
873 ++iter;
874 } while (iter != end);
875
876 return jsBoolean(true);
877}
878
879// ------------------------------ DeleteBracketNode -----------------------------------
880JSValue *DeleteBracketNode::evaluate(ExecState *exec)
881{
882 JSValue *baseValue = m_base->evaluate(exec);
883 KJS_CHECKEXCEPTIONVALUE
884 JSValue *subscript = m_subscript->evaluate(exec);
885 KJS_CHECKEXCEPTIONVALUE
886
887 JSObject *base = baseValue->toObject(exec);
888
889 uint32_t propertyIndex;
890 if (subscript->getUInt32(propertyIndex))
891 return jsBoolean(base->deleteProperty(exec, propertyIndex));
892
893 Identifier propertyName(subscript->toString(exec));
894 return jsBoolean(base->deleteProperty(exec, propertyName));
895}
896
897// ------------------------------ DeleteDotNode -----------------------------------
898JSValue *DeleteDotNode::evaluate(ExecState *exec)
899{
900 JSValue *baseValue = m_base->evaluate(exec);
901 JSObject *base = baseValue->toObject(exec);
902 KJS_CHECKEXCEPTIONVALUE
903
904 return jsBoolean(base->deleteProperty(exec, m_ident));
905}
906
907// ------------------------------ DeleteValueNode -----------------------------------
908JSValue *DeleteValueNode::evaluate(ExecState *exec)
909{
910 m_expr->evaluate(exec);
911 KJS_CHECKEXCEPTIONVALUE
912
913 // delete on a non-location expression ignores the value and returns true
914 return jsBoolean(true);
915}
916
917// ------------------------------ VoidNode -------------------------------------
918
919// ECMA 11.4.2
920JSValue *VoidNode::evaluate(ExecState *exec)
921{
922 expr->evaluate(exec);
923 KJS_CHECKEXCEPTIONVALUE
924
925 return jsUndefined();
926}
927
928// ECMA 11.4.3
929
930// ------------------------------ TypeOfValueNode -----------------------------------
931
932static JSValue *typeStringForValue(JSValue *v)
933{
934 switch (v->type()) {
935 case UndefinedType:
936 return jsString("undefined");
937 case NullType:
938 return jsString("object");
939 case BooleanType:
940 return jsString("boolean");
941 case NumberType:
942 return jsString("number");
943 case StringType:
944 return jsString("string");
945 default:
946 if (v->isObject()) {
947 // Return "undefined" for objects that should be treated
948 // as null when doing comparisons.
949 if (static_cast<JSObject*>(v)->masqueradeAsUndefined())
950 return jsString("undefined");
951 else if (static_cast<JSObject*>(v)->implementsCall())
952 return jsString("function");
953 }
954
955 return jsString("object");
956 }
957}
958
959JSValue *TypeOfResolveNode::evaluate(ExecState *exec)
960{
961 const ScopeChain& chain = exec->context().imp()->scopeChain();
962 ScopeChainIterator iter = chain.begin();
963 ScopeChainIterator end = chain.end();
964
965 // we must always have something in the scope chain
966 assert(iter != end);
967
968 PropertySlot slot;
969 JSObject *base;
970 do {
971 base = *iter;
972 if (base->getPropertySlot(exec, m_ident, slot)) {
973 JSValue *v = slot.getValue(exec, base, m_ident);
974 return typeStringForValue(v);
975 }
976
977 ++iter;
978 } while (iter != end);
979
980 return jsString("undefined");
981}
982
983// ------------------------------ TypeOfValueNode -----------------------------------
984
985JSValue *TypeOfValueNode::evaluate(ExecState *exec)
986{
987 JSValue *v = m_expr->evaluate(exec);
988 KJS_CHECKEXCEPTIONVALUE
989
990 return typeStringForValue(v);
991}
992
993// ECMA 11.4.4 and 11.4.5
994
995// ------------------------------ PrefixResolveNode ----------------------------------
996
997JSValue *PrefixResolveNode::evaluate(ExecState *exec)
998{
999 const ScopeChain& chain = exec->context().imp()->scopeChain();
1000 ScopeChainIterator iter = chain.begin();
1001 ScopeChainIterator end = chain.end();
1002
1003 // we must always have something in the scope chain
1004 assert(iter != end);
1005
1006 PropertySlot slot;
1007 JSObject *base;
1008 do {
1009 base = *iter;
1010 if (base->getPropertySlot(exec, m_ident, slot)) {
1011 JSValue *v = slot.getValue(exec, base, m_ident);
1012
1013 double n = v->toNumber(exec);
1014
1015 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
1016 JSValue *n2 = jsNumber(newValue);
1017 base->put(exec, m_ident, n2);
1018
1019 return n2;
1020 }
1021
1022 ++iter;
1023 } while (iter != end);
1024
1025 return throwUndefinedVariableError(exec, m_ident);
1026}
1027
1028// ------------------------------ PrefixBracketNode ----------------------------------
1029
1030JSValue *PrefixBracketNode::evaluate(ExecState *exec)
1031{
1032 JSValue *baseValue = m_base->evaluate(exec);
1033 KJS_CHECKEXCEPTIONVALUE
1034 JSValue *subscript = m_subscript->evaluate(exec);
1035 KJS_CHECKEXCEPTIONVALUE
1036
1037 JSObject *base = baseValue->toObject(exec);
1038
1039 uint32_t propertyIndex;
1040 if (subscript->getUInt32(propertyIndex)) {
1041 PropertySlot slot;
1042 JSValue *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1043 KJS_CHECKEXCEPTIONVALUE
1044
1045 double n = v->toNumber(exec);
1046
1047 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
1048 JSValue *n2 = jsNumber(newValue);
1049 base->put(exec, propertyIndex, n2);
1050
1051 return n2;
1052 }
1053
1054 Identifier propertyName(subscript->toString(exec));
1055 PropertySlot slot;
1056 JSValue *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1057 KJS_CHECKEXCEPTIONVALUE
1058
1059 double n = v->toNumber(exec);
1060
1061 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
1062 JSValue *n2 = jsNumber(newValue);
1063 base->put(exec, propertyName, n2);
1064
1065 return n2;
1066}
1067
1068// ------------------------------ PrefixDotNode ----------------------------------
1069
1070JSValue *PrefixDotNode::evaluate(ExecState *exec)
1071{
1072 JSValue *baseValue = m_base->evaluate(exec);
1073 KJS_CHECKEXCEPTIONVALUE
1074 JSObject *base = baseValue->toObject(exec);
1075
1076 PropertySlot slot;
1077 JSValue *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1078 KJS_CHECKEXCEPTIONVALUE
1079
1080 double n = v->toNumber(exec);
1081
1082 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
1083 JSValue *n2 = jsNumber(newValue);
1084 base->put(exec, m_ident, n2);
1085
1086 return n2;
1087}
1088
1089// ------------------------------ UnaryPlusNode --------------------------------
1090
1091// ECMA 11.4.6
1092JSValue *UnaryPlusNode::evaluate(ExecState *exec)
1093{
1094 JSValue *v = expr->evaluate(exec);
1095 KJS_CHECKEXCEPTIONVALUE
1096
1097 return jsNumber(v->toNumber(exec));
1098}
1099
1100// ------------------------------ NegateNode -----------------------------------
1101
1102// ECMA 11.4.7
1103JSValue *NegateNode::evaluate(ExecState *exec)
1104{
1105 JSValue *v = expr->evaluate(exec);
1106 KJS_CHECKEXCEPTIONVALUE
1107
1108 double n = v->toNumber(exec);
1109 return jsNumber(-n);
1110}
1111
1112// ------------------------------ BitwiseNotNode -------------------------------
1113
1114// ECMA 11.4.8
1115JSValue *BitwiseNotNode::evaluate(ExecState *exec)
1116{
1117 JSValue *v = expr->evaluate(exec);
1118 KJS_CHECKEXCEPTIONVALUE
1119 return jsNumber(~v->toInt32(exec));
1120}
1121
1122// ------------------------------ LogicalNotNode -------------------------------
1123
1124// ECMA 11.4.9
1125JSValue *LogicalNotNode::evaluate(ExecState *exec)
1126{
1127 JSValue *v = expr->evaluate(exec);
1128 KJS_CHECKEXCEPTIONVALUE
1129 return jsBoolean(!v->toBoolean(exec));
1130}
1131
1132// ------------------------------ MultNode -------------------------------------
1133
1134// ECMA 11.5
1135JSValue *MultNode::evaluate(ExecState *exec)
1136{
1137 JSValue *v1 = term1->evaluate(exec);
1138 KJS_CHECKEXCEPTIONVALUE
1139
1140 JSValue *v2 = term2->evaluate(exec);
1141 KJS_CHECKEXCEPTIONVALUE
1142
1143 return mult(exec, v1, v2, oper);
1144}
1145
1146// ------------------------------ AddNode --------------------------------------
1147
1148// ECMA 11.6
1149JSValue *AddNode::evaluate(ExecState *exec)
1150{
1151 JSValue *v1 = term1->evaluate(exec);
1152 KJS_CHECKEXCEPTIONVALUE
1153
1154 JSValue *v2 = term2->evaluate(exec);
1155 KJS_CHECKEXCEPTIONVALUE
1156
1157 return add(exec, v1, v2, oper);
1158}
1159
1160// ------------------------------ ShiftNode ------------------------------------
1161
1162// ECMA 11.7
1163JSValue *ShiftNode::evaluate(ExecState *exec)
1164{
1165 JSValue *v1 = term1->evaluate(exec);
1166 KJS_CHECKEXCEPTIONVALUE
1167 JSValue *v2 = term2->evaluate(exec);
1168 KJS_CHECKEXCEPTIONVALUE
1169 unsigned int i2 = v2->toUInt32(exec);
1170 i2 &= 0x1f;
1171
1172 switch (oper) {
1173 case OpLShift:
1174 return jsNumber(v1->toInt32(exec) << i2);
1175 case OpRShift:
1176 return jsNumber(v1->toInt32(exec) >> i2);
1177 case OpURShift:
1178 return jsNumber(v1->toUInt32(exec) >> i2);
1179 default:
1180 assert(!"ShiftNode: unhandled switch case");
1181 return jsUndefined();
1182 }
1183}
1184
1185// ------------------------------ RelationalNode -------------------------------
1186
1187// ECMA 11.8
1188JSValue *RelationalNode::evaluate(ExecState *exec)
1189{
1190 JSValue *v1 = expr1->evaluate(exec);
1191 KJS_CHECKEXCEPTIONVALUE
1192 JSValue *v2 = expr2->evaluate(exec);
1193 KJS_CHECKEXCEPTIONVALUE
1194
1195 bool b;
1196 if (oper == OpLess || oper == OpGreaterEq) {
1197 int r = relation(exec, v1, v2);
1198 if (r < 0)
1199 b = false;
1200 else
1201 b = (oper == OpLess) ? (r == 1) : (r == 0);
1202 } else if (oper == OpGreater || oper == OpLessEq) {
1203 int r = relation(exec, v2, v1);
1204 if (r < 0)
1205 b = false;
1206 else
1207 b = (oper == OpGreater) ? (r == 1) : (r == 0);
1208 } else if (oper == OpIn) {
1209 // Is all of this OK for host objects?
1210 if (!v2->isObject())
1211 return throwError(exec, TypeError,
1212 "Value %s (result of expression %s) is not an object. Cannot be used with IN expression.", v2, expr2.get());
1213 JSObject *o2(static_cast<JSObject*>(v2));
1214 b = o2->hasProperty(exec, Identifier(v1->toString(exec)));
1215 } else {
1216 if (!v2->isObject())
1217 return throwError(exec, TypeError,
1218 "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, expr2.get());
1219
1220 JSObject *o2(static_cast<JSObject*>(v2));
1221 if (!o2->implementsHasInstance()) {
1222 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
1223 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
1224 // property. It seems that all object have the property, but not all implement it, so in this
1225 // case we return false (consistent with mozilla)
1226 return jsBoolean(false);
1227 // return throwError(exec, TypeError,
1228 // "Object does not implement the [[HasInstance]] method." );
1229 }
1230 return jsBoolean(o2->hasInstance(exec, v1));
1231 }
1232
1233 return jsBoolean(b);
1234}
1235
1236// ------------------------------ EqualNode ------------------------------------
1237
1238// ECMA 11.9
1239JSValue *EqualNode::evaluate(ExecState *exec)
1240{
1241 JSValue *v1 = expr1->evaluate(exec);
1242 KJS_CHECKEXCEPTIONVALUE
1243 JSValue *v2 = expr2->evaluate(exec);
1244 KJS_CHECKEXCEPTIONVALUE
1245
1246 bool result;
1247 if (oper == OpEqEq || oper == OpNotEq) {
1248 // == and !=
1249 bool eq = equal(exec,v1, v2);
1250 result = oper == OpEqEq ? eq : !eq;
1251 } else {
1252 // === and !==
1253 bool eq = strictEqual(exec,v1, v2);
1254 result = oper == OpStrEq ? eq : !eq;
1255 }
1256 return jsBoolean(result);
1257}
1258
1259// ------------------------------ BitOperNode ----------------------------------
1260
1261// ECMA 11.10
1262JSValue *BitOperNode::evaluate(ExecState *exec)
1263{
1264 JSValue *v1 = expr1->evaluate(exec);
1265 KJS_CHECKEXCEPTIONVALUE
1266 JSValue *v2 = expr2->evaluate(exec);
1267 KJS_CHECKEXCEPTIONVALUE
1268 int i1 = v1->toInt32(exec);
1269 int i2 = v2->toInt32(exec);
1270 int result;
1271 if (oper == OpBitAnd)
1272 result = i1 & i2;
1273 else if (oper == OpBitXOr)
1274 result = i1 ^ i2;
1275 else
1276 result = i1 | i2;
1277
1278 return jsNumber(result);
1279}
1280
1281// ------------------------------ BinaryLogicalNode ----------------------------
1282
1283// ECMA 11.11
1284JSValue *BinaryLogicalNode::evaluate(ExecState *exec)
1285{
1286 JSValue *v1 = expr1->evaluate(exec);
1287 KJS_CHECKEXCEPTIONVALUE
1288 bool b1 = v1->toBoolean(exec);
1289 if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
1290 return v1;
1291
1292 JSValue *v2 = expr2->evaluate(exec);
1293 KJS_CHECKEXCEPTIONVALUE
1294
1295 return v2;
1296}
1297
1298// ------------------------------ ConditionalNode ------------------------------
1299
1300// ECMA 11.12
1301JSValue *ConditionalNode::evaluate(ExecState *exec)
1302{
1303 JSValue *v = logical->evaluate(exec);
1304 KJS_CHECKEXCEPTIONVALUE
1305 bool b = v->toBoolean(exec);
1306
1307 if (b)
1308 v = expr1->evaluate(exec);
1309 else
1310 v = expr2->evaluate(exec);
1311 KJS_CHECKEXCEPTIONVALUE
1312
1313 return v;
1314}
1315
1316// ECMA 11.13
1317
1318static ALWAYS_INLINE JSValue *valueForReadModifyAssignment(ExecState * exec, JSValue *v1, JSValue *v2, Operator oper)
1319{
1320 JSValue *v;
1321 int i1;
1322 int i2;
1323 unsigned int ui;
1324 switch (oper) {
1325 case OpMultEq:
1326 v = mult(exec, v1, v2, '*');
1327 break;
1328 case OpDivEq:
1329 v = mult(exec, v1, v2, '/');
1330 break;
1331 case OpPlusEq:
1332 v = add(exec, v1, v2, '+');
1333 break;
1334 case OpMinusEq:
1335 v = add(exec, v1, v2, '-');
1336 break;
1337 case OpLShift:
1338 i1 = v1->toInt32(exec);
1339 i2 = v2->toInt32(exec);
1340 v = jsNumber(i1 << i2);
1341 break;
1342 case OpRShift:
1343 i1 = v1->toInt32(exec);
1344 i2 = v2->toInt32(exec);
1345 v = jsNumber(i1 >> i2);
1346 break;
1347 case OpURShift:
1348 ui = v1->toUInt32(exec);
1349 i2 = v2->toInt32(exec);
1350 v = jsNumber(ui >> i2);
1351 break;
1352 case OpAndEq:
1353 i1 = v1->toInt32(exec);
1354 i2 = v2->toInt32(exec);
1355 v = jsNumber(i1 & i2);
1356 break;
1357 case OpXOrEq:
1358 i1 = v1->toInt32(exec);
1359 i2 = v2->toInt32(exec);
1360 v = jsNumber(i1 ^ i2);
1361 break;
1362 case OpOrEq:
1363 i1 = v1->toInt32(exec);
1364 i2 = v2->toInt32(exec);
1365 v = jsNumber(i1 | i2);
1366 break;
1367 case OpModEq: {
1368 double d1 = v1->toNumber(exec);
1369 double d2 = v2->toNumber(exec);
1370 v = jsNumber(fmod(d1, d2));
1371 }
1372 break;
1373 default:
1374 assert(0);
1375 v = jsUndefined();
1376 }
1377
1378 return v;
1379}
1380
1381// ------------------------------ AssignResolveNode -----------------------------------
1382
1383JSValue *AssignResolveNode::evaluate(ExecState *exec)
1384{
1385 const ScopeChain& chain = exec->context().imp()->scopeChain();
1386 ScopeChainIterator iter = chain.begin();
1387 ScopeChainIterator end = chain.end();
1388
1389 // we must always have something in the scope chain
1390 assert(iter != end);
1391
1392 PropertySlot slot;
1393 JSObject *base;
1394 do {
1395 base = *iter;
1396 if (base->getPropertySlot(exec, m_ident, slot))
1397 goto found;
1398
1399 ++iter;
1400 } while (iter != end);
1401
1402 if (m_oper != OpEqual)
1403 return throwUndefinedVariableError(exec, m_ident);
1404
1405 found:
1406 JSValue *v;
1407
1408 if (m_oper == OpEqual) {
1409 v = m_right->evaluate(exec);
1410 } else {
1411 JSValue *v1 = slot.getValue(exec, base, m_ident);
1412 KJS_CHECKEXCEPTIONVALUE
1413 JSValue *v2 = m_right->evaluate(exec);
1414 v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
1415 }
1416
1417 KJS_CHECKEXCEPTIONVALUE
1418
1419 base->put(exec, m_ident, v);
1420 return v;
1421}
1422
1423// ------------------------------ AssignDotNode -----------------------------------
1424
1425JSValue *AssignDotNode::evaluate(ExecState *exec)
1426{
1427 JSValue *baseValue = m_base->evaluate(exec);
1428 KJS_CHECKEXCEPTIONVALUE
1429 JSObject *base = baseValue->toObject(exec);
1430
1431 JSValue *v;
1432
1433 if (m_oper == OpEqual) {
1434 v = m_right->evaluate(exec);
1435 } else {
1436 PropertySlot slot;
1437 JSValue *v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, base, m_ident) : jsUndefined();
1438 KJS_CHECKEXCEPTIONVALUE
1439 JSValue *v2 = m_right->evaluate(exec);
1440 v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
1441 }
1442
1443 KJS_CHECKEXCEPTIONVALUE
1444
1445 base->put(exec, m_ident, v);
1446 return v;
1447}
1448
1449// ------------------------------ AssignBracketNode -----------------------------------
1450
1451JSValue *AssignBracketNode::evaluate(ExecState *exec)
1452{
1453 JSValue *baseValue = m_base->evaluate(exec);
1454 KJS_CHECKEXCEPTIONVALUE
1455 JSValue *subscript = m_subscript->evaluate(exec);
1456 KJS_CHECKEXCEPTIONVALUE
1457
1458 JSObject *base = baseValue->toObject(exec);
1459
1460 uint32_t propertyIndex;
1461 if (subscript->getUInt32(propertyIndex)) {
1462 JSValue *v;
1463 if (m_oper == OpEqual) {
1464 v = m_right->evaluate(exec);
1465 } else {
1466 PropertySlot slot;
1467 JSValue *v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, base, propertyIndex) : jsUndefined();
1468 KJS_CHECKEXCEPTIONVALUE
1469 JSValue *v2 = m_right->evaluate(exec);
1470 v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
1471 }
1472
1473 KJS_CHECKEXCEPTIONVALUE
1474
1475 base->put(exec, propertyIndex, v);
1476 return v;
1477 }
1478
1479 Identifier propertyName(subscript->toString(exec));
1480 JSValue *v;
1481
1482 if (m_oper == OpEqual) {
1483 v = m_right->evaluate(exec);
1484 } else {
1485 PropertySlot slot;
1486 JSValue *v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, base, propertyName) : jsUndefined();
1487 KJS_CHECKEXCEPTIONVALUE
1488 JSValue *v2 = m_right->evaluate(exec);
1489 v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
1490 }
1491
1492 KJS_CHECKEXCEPTIONVALUE
1493
1494 base->put(exec, propertyName, v);
1495 return v;
1496}
1497
1498// ------------------------------ CommaNode ------------------------------------
1499
1500// ECMA 11.14
1501JSValue *CommaNode::evaluate(ExecState *exec)
1502{
1503 expr1->evaluate(exec);
1504 KJS_CHECKEXCEPTIONVALUE
1505 JSValue *v = expr2->evaluate(exec);
1506 KJS_CHECKEXCEPTIONVALUE
1507
1508 return v;
1509}
1510
1511// ------------------------------ StatListNode ---------------------------------
1512
1513StatListNode::StatListNode(StatementNode *s)
1514 : statement(s), next(this)
1515{
1516 Parser::noteNodeCycle(this);
1517 setLoc(s->firstLine(), s->lastLine());
1518}
1519
1520StatListNode::StatListNode(StatListNode *l, StatementNode *s)
1521 : statement(s), next(l->next)
1522{
1523 l->next = this;
1524 setLoc(l->firstLine(), s->lastLine());
1525}
1526
1527// ECMA 12.1
1528Completion StatListNode::execute(ExecState *exec)
1529{
1530 Completion c = statement->execute(exec);
1531 KJS_ABORTPOINT
1532 if (c.complType() != Normal)
1533 return c;
1534
1535 JSValue *v = c.value();
1536
1537 for (StatListNode *n = next.get(); n; n = n->next.get()) {
1538 Completion c2 = n->statement->execute(exec);
1539 KJS_ABORTPOINT
1540 if (c2.complType() != Normal)
1541 return c2;
1542
1543 if (c2.isValueCompletion())
1544 v = c2.value();
1545 c = c2;
1546 }
1547
1548 return Completion(c.complType(), v, c.target());
1549}
1550
1551void StatListNode::processVarDecls(ExecState *exec)
1552{
1553 for (StatListNode *n = this; n; n = n->next.get())
1554 n->statement->processVarDecls(exec);
1555}
1556
1557void StatListNode::breakCycle()
1558{
1559 next = 0;
1560}
1561
1562// ------------------------------ AssignExprNode -------------------------------
1563
1564// ECMA 12.2
1565JSValue *AssignExprNode::evaluate(ExecState *exec)
1566{
1567 return expr->evaluate(exec);
1568}
1569
1570// ------------------------------ VarDeclNode ----------------------------------
1571
1572
1573VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in, Type t)
1574 : varType(t), ident(id), init(in)
1575{
1576}
1577
1578// ECMA 12.2
1579JSValue *VarDeclNode::evaluate(ExecState *exec)
1580{
1581 JSObject *variable = exec->context().imp()->variableObject();
1582
1583 JSValue *val;
1584 if (init) {
1585 val = init->evaluate(exec);
1586 KJS_CHECKEXCEPTIONVALUE
1587 } else {
1588 // already declared? - check with getDirect so you can override
1589 // built-in properties of the global object with var declarations.
1590 if (variable->getDirect(ident))
1591 return 0;
1592 val = jsUndefined();
1593 }
1594
1595#ifdef KJS_VERBOSE
1596 printInfo(exec,(UString("new variable ")+ident.ustring()).cstring().c_str(),val);
1597#endif
1598 // We use Internal to bypass all checks in derived objects, e.g. so that
1599 // "var location" creates a dynamic property instead of activating window.location.
1600 int flags = Internal;
1601 if (exec->context().imp()->codeType() != EvalCode)
1602 flags |= DontDelete;
1603 if (varType == VarDeclNode::Constant)
1604 flags |= ReadOnly;
1605 variable->put(exec, ident, val, flags);
1606
1607 return jsString(ident.ustring());
1608}
1609
1610void VarDeclNode::processVarDecls(ExecState *exec)
1611{
1612 JSObject *variable = exec->context().imp()->variableObject();
1613
1614 // If a variable by this name already exists, don't clobber it -
1615 // it might be a function parameter
1616 if (!variable->hasProperty(exec, ident)) {
1617 int flags = Internal;
1618 if (exec->context().imp()->codeType() != EvalCode)
1619 flags |= DontDelete;
1620 if (varType == VarDeclNode::Constant)
1621 flags |= ReadOnly;
1622 variable->put(exec, ident, jsUndefined(), flags);
1623 }
1624}
1625
1626// ------------------------------ VarDeclListNode ------------------------------
1627
1628// ECMA 12.2
1629JSValue *VarDeclListNode::evaluate(ExecState *exec)
1630{
1631 for (VarDeclListNode *n = this; n; n = n->next.get()) {
1632 n->var->evaluate(exec);
1633 KJS_CHECKEXCEPTIONVALUE
1634 }
1635 return jsUndefined();
1636}
1637
1638void VarDeclListNode::processVarDecls(ExecState *exec)
1639{
1640 for (VarDeclListNode *n = this; n; n = n->next.get())
1641 n->var->processVarDecls(exec);
1642}
1643
1644void VarDeclListNode::breakCycle()
1645{
1646 next = 0;
1647}
1648
1649// ------------------------------ VarStatementNode -----------------------------
1650
1651// ECMA 12.2
1652Completion VarStatementNode::execute(ExecState *exec)
1653{
1654 KJS_BREAKPOINT;
1655
1656 (void) next->evaluate(exec);
1657 KJS_CHECKEXCEPTION
1658
1659 return Completion(Normal);
1660}
1661
1662void VarStatementNode::processVarDecls(ExecState *exec)
1663{
1664 next->processVarDecls(exec);
1665}
1666
1667// ------------------------------ BlockNode ------------------------------------
1668
1669BlockNode::BlockNode(SourceElementsNode *s)
1670{
1671 if (s) {
1672 source = s->next.release();
1673 Parser::removeNodeCycle(source.get());
1674 setLoc(s->firstLine(), s->lastLine());
1675 } else {
1676 source = 0;
1677 }
1678}
1679
1680// ECMA 12.1
1681Completion BlockNode::execute(ExecState *exec)
1682{
1683 if (!source)
1684 return Completion(Normal);
1685
1686 source->processFuncDecl(exec);
1687
1688 return source->execute(exec);
1689}
1690
1691void BlockNode::processVarDecls(ExecState *exec)
1692{
1693 if (source)
1694 source->processVarDecls(exec);
1695}
1696
1697// ------------------------------ EmptyStatementNode ---------------------------
1698
1699// ECMA 12.3
1700Completion EmptyStatementNode::execute(ExecState *)
1701{
1702 return Completion(Normal);
1703}
1704
1705// ------------------------------ ExprStatementNode ----------------------------
1706
1707// ECMA 12.4
1708Completion ExprStatementNode::execute(ExecState *exec)
1709{
1710 KJS_BREAKPOINT;
1711
1712 JSValue *v = expr->evaluate(exec);
1713 KJS_CHECKEXCEPTION
1714
1715 return Completion(Normal, v);
1716}
1717
1718// ------------------------------ IfNode ---------------------------------------
1719
1720// ECMA 12.5
1721Completion IfNode::execute(ExecState *exec)
1722{
1723 KJS_BREAKPOINT;
1724
1725 JSValue *v = expr->evaluate(exec);
1726 KJS_CHECKEXCEPTION
1727 bool b = v->toBoolean(exec);
1728
1729 // if ... then
1730 if (b)
1731 return statement1->execute(exec);
1732
1733 // no else
1734 if (!statement2)
1735 return Completion(Normal);
1736
1737 // else
1738 return statement2->execute(exec);
1739}
1740
1741void IfNode::processVarDecls(ExecState *exec)
1742{
1743 statement1->processVarDecls(exec);
1744
1745 if (statement2)
1746 statement2->processVarDecls(exec);
1747}
1748
1749// ------------------------------ DoWhileNode ----------------------------------
1750
1751// ECMA 12.6.1
1752Completion DoWhileNode::execute(ExecState *exec)
1753{
1754 KJS_BREAKPOINT;
1755
1756 JSValue *bv;
1757 Completion c;
1758
1759 do {
1760 // bail out on error
1761 KJS_CHECKEXCEPTION
1762
1763 exec->context().imp()->pushIteration();
1764 c = statement->execute(exec);
1765 exec->context().imp()->popIteration();
1766 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1767 if ((c.complType() == Break) && ls.contains(c.target()))
1768 return Completion(Normal, 0);
1769 if (c.complType() != Normal)
1770 return c;
1771 }
1772 bv = expr->evaluate(exec);
1773 KJS_CHECKEXCEPTION
1774 } while (bv->toBoolean(exec));
1775
1776 return Completion(Normal, 0);
1777}
1778
1779void DoWhileNode::processVarDecls(ExecState *exec)
1780{
1781 statement->processVarDecls(exec);
1782}
1783
1784// ------------------------------ WhileNode ------------------------------------
1785
1786// ECMA 12.6.2
1787Completion WhileNode::execute(ExecState *exec)
1788{
1789 KJS_BREAKPOINT;
1790
1791 JSValue *bv;
1792 Completion c;
1793 bool b(false);
1794 JSValue *value = 0;
1795
1796 while (1) {
1797 bv = expr->evaluate(exec);
1798 KJS_CHECKEXCEPTION
1799 b = bv->toBoolean(exec);
1800
1801 // bail out on error
1802 KJS_CHECKEXCEPTION
1803
1804 if (!b)
1805 return Completion(Normal, value);
1806
1807 exec->context().imp()->pushIteration();
1808 c = statement->execute(exec);
1809 exec->context().imp()->popIteration();
1810 if (c.isValueCompletion())
1811 value = c.value();
1812
1813 if ((c.complType() == Continue) && ls.contains(c.target()))
1814 continue;
1815 if ((c.complType() == Break) && ls.contains(c.target()))
1816 return Completion(Normal, value);
1817 if (c.complType() != Normal)
1818 return c;
1819 }
1820
1821 return Completion(); // work around gcc 4.0 bug
1822}
1823
1824void WhileNode::processVarDecls(ExecState *exec)
1825{
1826 statement->processVarDecls(exec);
1827}
1828
1829// ------------------------------ ForNode --------------------------------------
1830
1831// ECMA 12.6.3
1832Completion ForNode::execute(ExecState *exec)
1833{
1834 JSValue *v, *cval = 0;
1835
1836 if (expr1) {
1837 v = expr1->evaluate(exec);
1838 KJS_CHECKEXCEPTION
1839 }
1840 while (1) {
1841 if (expr2) {
1842 v = expr2->evaluate(exec);
1843 KJS_CHECKEXCEPTION
1844 if (!v->toBoolean(exec))
1845 return Completion(Normal, cval);
1846 }
1847 // bail out on error
1848 KJS_CHECKEXCEPTION
1849
1850 exec->context().imp()->pushIteration();
1851 Completion c = statement->execute(exec);
1852 exec->context().imp()->popIteration();
1853 if (c.isValueCompletion())
1854 cval = c.value();
1855 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1856 if ((c.complType() == Break) && ls.contains(c.target()))
1857 return Completion(Normal, cval);
1858 if (c.complType() != Normal)
1859 return c;
1860 }
1861 if (expr3) {
1862 v = expr3->evaluate(exec);
1863 KJS_CHECKEXCEPTION
1864 }
1865 }
1866
1867 return Completion(); // work around gcc 4.0 bug
1868}
1869
1870void ForNode::processVarDecls(ExecState *exec)
1871{
1872 if (expr1)
1873 expr1->processVarDecls(exec);
1874
1875 statement->processVarDecls(exec);
1876}
1877
1878// ------------------------------ ForInNode ------------------------------------
1879
1880ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
1881 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
1882{
1883}
1884
1885ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
1886 : ident(i), init(in), expr(e), statement(s)
1887{
1888 // for( var foo = bar in baz )
1889 varDecl = new VarDeclNode(ident, init.get(), VarDeclNode::Variable);
1890 lexpr = new ResolveNode(ident);
1891}
1892
1893// ECMA 12.6.4
1894Completion ForInNode::execute(ExecState *exec)
1895{
1896 JSValue *e;
1897 JSValue *retval = 0;
1898 JSObject *v;
1899 Completion c;
1900 ReferenceList propList;
1901
1902 if (varDecl) {
1903 varDecl->evaluate(exec);
1904 KJS_CHECKEXCEPTION
1905 }
1906
1907 e = expr->evaluate(exec);
1908
1909 // for Null and Undefined, we want to make sure not to go through
1910 // the loop at all, because their object wrappers will have a
1911 // property list but will throw an exception if you attempt to
1912 // access any property.
1913 if (e->isUndefinedOrNull()) {
1914 return Completion(Normal, 0);
1915 }
1916
1917 KJS_CHECKEXCEPTION
1918 v = e->toObject(exec);
1919 propList = v->propList(exec);
1920
1921 ReferenceListIterator propIt = propList.begin();
1922
1923 while (propIt != propList.end()) {
1924 Identifier name = propIt->getPropertyName(exec);
1925 if (!v->hasProperty(exec, name)) {
1926 propIt++;
1927 continue;
1928 }
1929
1930 JSValue *str = jsString(name.ustring());
1931
1932 if (lexpr->isResolveNode()) {
1933 const Identifier &ident = static_cast<ResolveNode *>(lexpr.get())->identifier();
1934
1935 const ScopeChain& chain = exec->context().imp()->scopeChain();
1936 ScopeChainIterator iter = chain.begin();
1937 ScopeChainIterator end = chain.end();
1938
1939 // we must always have something in the scope chain
1940 assert(iter != end);
1941
1942 PropertySlot slot;
1943 JSObject *o;
1944 do {
1945 o = *iter;
1946 if (o->getPropertySlot(exec, ident, slot)) {
1947 o->put(exec, ident, str);
1948 break;
1949 }
1950 ++iter;
1951 } while (iter != end);
1952
1953 if (iter == end)
1954 o->put(exec, ident, str);
1955 } else if (lexpr->isDotAccessorNode()) {
1956 const Identifier& ident = static_cast<DotAccessorNode *>(lexpr.get())->identifier();
1957 JSValue *v = static_cast<DotAccessorNode *>(lexpr.get())->base()->evaluate(exec);
1958 KJS_CHECKEXCEPTION
1959 JSObject *o = v->toObject(exec);
1960
1961 o->put(exec, ident, str);
1962 } else {
1963 assert(lexpr->isBracketAccessorNode());
1964 JSValue *v = static_cast<BracketAccessorNode *>(lexpr.get())->base()->evaluate(exec);
1965 KJS_CHECKEXCEPTION
1966 JSValue *v2 = static_cast<BracketAccessorNode *>(lexpr.get())->subscript()->evaluate(exec);
1967 KJS_CHECKEXCEPTION
1968 JSObject *o = v->toObject(exec);
1969
1970 uint32_t i;
1971 if (v2->getUInt32(i))
1972 o->put(exec, i, str);
1973 o->put(exec, Identifier(v2->toString(exec)), str);
1974 }
1975
1976 KJS_CHECKEXCEPTION
1977
1978 exec->context().imp()->pushIteration();
1979 c = statement->execute(exec);
1980 exec->context().imp()->popIteration();
1981 if (c.isValueCompletion())
1982 retval = c.value();
1983
1984 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1985 if ((c.complType() == Break) && ls.contains(c.target()))
1986 break;
1987 if (c.complType() != Normal) {
1988 return c;
1989 }
1990 }
1991
1992 propIt++;
1993 }
1994
1995 // bail out on error
1996 KJS_CHECKEXCEPTION
1997
1998 return Completion(Normal, retval);
1999}
2000
2001void ForInNode::processVarDecls(ExecState *exec)
2002{
2003 if (varDecl)
2004 varDecl->processVarDecls(exec);
2005 statement->processVarDecls(exec);
2006}
2007
2008// ------------------------------ ContinueNode ---------------------------------
2009
2010// ECMA 12.7
2011Completion ContinueNode::execute(ExecState *exec)
2012{
2013 KJS_BREAKPOINT;
2014
2015 if (ident.isEmpty() && !exec->context().imp()->inIteration())
2016 return createErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
2017 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
2018 return createErrorCompletion(exec, SyntaxError, "Label %s not found.", ident);
2019 else
2020 return Completion(Continue, 0, ident);
2021}
2022
2023// ------------------------------ BreakNode ------------------------------------
2024
2025// ECMA 12.8
2026Completion BreakNode::execute(ExecState *exec)
2027{
2028 KJS_BREAKPOINT;
2029
2030 if (ident.isEmpty() && !exec->context().imp()->inIteration() &&
2031 !exec->context().imp()->inSwitch())
2032 return createErrorCompletion(exec, SyntaxError, "Invalid break statement.");
2033 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
2034 return createErrorCompletion(exec, SyntaxError, "Label %s not found.");
2035 else
2036 return Completion(Break, 0, ident);
2037}
2038
2039// ------------------------------ ReturnNode -----------------------------------
2040
2041// ECMA 12.9
2042Completion ReturnNode::execute(ExecState *exec)
2043{
2044 KJS_BREAKPOINT;
2045
2046 CodeType codeType = exec->context().imp()->codeType();
2047 if (codeType != FunctionCode && codeType != AnonymousCode ) {
2048 return createErrorCompletion(exec, SyntaxError, "Invalid return statement.");
2049 }
2050
2051 if (!value)
2052 return Completion(ReturnValue, jsUndefined());
2053
2054 JSValue *v = value->evaluate(exec);
2055 KJS_CHECKEXCEPTION
2056
2057 return Completion(ReturnValue, v);
2058}
2059
2060// ------------------------------ WithNode -------------------------------------
2061
2062// ECMA 12.10
2063Completion WithNode::execute(ExecState *exec)
2064{
2065 KJS_BREAKPOINT;
2066
2067 JSValue *v = expr->evaluate(exec);
2068 KJS_CHECKEXCEPTION
2069 JSObject *o = v->toObject(exec);
2070 KJS_CHECKEXCEPTION
2071 exec->context().imp()->pushScope(o);
2072 Completion res = statement->execute(exec);
2073 exec->context().imp()->popScope();
2074
2075 return res;
2076}
2077
2078void WithNode::processVarDecls(ExecState *exec)
2079{
2080 statement->processVarDecls(exec);
2081}
2082
2083// ------------------------------ CaseClauseNode -------------------------------
2084
2085// ECMA 12.11
2086JSValue *CaseClauseNode::evaluate(ExecState *exec)
2087{
2088 JSValue *v = expr->evaluate(exec);
2089 KJS_CHECKEXCEPTIONVALUE
2090
2091 return v;
2092}
2093
2094// ECMA 12.11
2095Completion CaseClauseNode::evalStatements(ExecState *exec)
2096{
2097 if (next)
2098 return next->execute(exec);
2099 else
2100 return Completion(Normal, jsUndefined());
2101}
2102
2103void CaseClauseNode::processVarDecls(ExecState *exec)
2104{
2105 if (next)
2106 next->processVarDecls(exec);
2107}
2108
2109// ------------------------------ ClauseListNode -------------------------------
2110
2111JSValue *ClauseListNode::evaluate(ExecState *)
2112{
2113 // should never be called
2114 assert(false);
2115 return 0;
2116}
2117
2118// ECMA 12.11
2119void ClauseListNode::processVarDecls(ExecState *exec)
2120{
2121 for (ClauseListNode *n = this; n; n = n->next.get())
2122 if (n->clause)
2123 n->clause->processVarDecls(exec);
2124}
2125
2126void ClauseListNode::breakCycle()
2127{
2128 next = 0;
2129}
2130
2131// ------------------------------ CaseBlockNode --------------------------------
2132
2133CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
2134 ClauseListNode *l2)
2135{
2136 if (l1) {
2137 list1 = l1->next.release();
2138 Parser::removeNodeCycle(list1.get());
2139 } else {
2140 list1 = 0;
2141 }
2142
2143 def = d;
2144
2145 if (l2) {
2146 list2 = l2->next.release();
2147 Parser::removeNodeCycle(list2.get());
2148 } else {
2149 list2 = 0;
2150 }
2151}
2152
2153JSValue *CaseBlockNode::evaluate(ExecState *)
2154{
2155 // should never be called
2156 assert(false);
2157 return 0;
2158}
2159
2160// ECMA 12.11
2161Completion CaseBlockNode::evalBlock(ExecState *exec, JSValue *input)
2162{
2163 JSValue *v;
2164 Completion res;
2165 ClauseListNode *a = list1.get();
2166 ClauseListNode *b = list2.get();
2167 CaseClauseNode *clause;
2168
2169 while (a) {
2170 clause = a->getClause();
2171 a = a->getNext();
2172 v = clause->evaluate(exec);
2173 KJS_CHECKEXCEPTION
2174 if (strictEqual(exec, input, v)) {
2175 res = clause->evalStatements(exec);
2176 if (res.complType() != Normal)
2177 return res;
2178 while (a) {
2179 res = a->getClause()->evalStatements(exec);
2180 if (res.complType() != Normal)
2181 return res;
2182 a = a->getNext();
2183 }
2184 break;
2185 }
2186 }
2187
2188 while (b) {
2189 clause = b->getClause();
2190 b = b->getNext();
2191 v = clause->evaluate(exec);
2192 KJS_CHECKEXCEPTION
2193 if (strictEqual(exec, input, v)) {
2194 res = clause->evalStatements(exec);
2195 if (res.complType() != Normal)
2196 return res;
2197 goto step18;
2198 }
2199 }
2200
2201 // default clause
2202 if (def) {
2203 res = def->evalStatements(exec);
2204 if (res.complType() != Normal)
2205 return res;
2206 }
2207 b = list2.get();
2208 step18:
2209 while (b) {
2210 clause = b->getClause();
2211 res = clause->evalStatements(exec);
2212 if (res.complType() != Normal)
2213 return res;
2214 b = b->getNext();
2215 }
2216
2217 // bail out on error
2218 KJS_CHECKEXCEPTION
2219
2220 return Completion(Normal);
2221}
2222
2223void CaseBlockNode::processVarDecls(ExecState *exec)
2224{
2225 if (list1)
2226 list1->processVarDecls(exec);
2227 if (def)
2228 def->processVarDecls(exec);
2229 if (list2)
2230 list2->processVarDecls(exec);
2231}
2232
2233// ------------------------------ SwitchNode -----------------------------------
2234
2235// ECMA 12.11
2236Completion SwitchNode::execute(ExecState *exec)
2237{
2238 KJS_BREAKPOINT;
2239
2240 JSValue *v = expr->evaluate(exec);
2241 KJS_CHECKEXCEPTION
2242
2243 exec->context().imp()->pushSwitch();
2244 Completion res = block->evalBlock(exec,v);
2245 exec->context().imp()->popSwitch();
2246
2247 if ((res.complType() == Break) && ls.contains(res.target()))
2248 return Completion(Normal, res.value());
2249 return res;
2250}
2251
2252void SwitchNode::processVarDecls(ExecState *exec)
2253{
2254 block->processVarDecls(exec);
2255}
2256
2257// ------------------------------ LabelNode ------------------------------------
2258
2259// ECMA 12.12
2260Completion LabelNode::execute(ExecState *exec)
2261{
2262 if (!exec->context().imp()->seenLabels()->push(label))
2263 return createErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", label);
2264 Completion e = statement->execute(exec);
2265 exec->context().imp()->seenLabels()->pop();
2266
2267 if ((e.complType() == Break) && (e.target() == label))
2268 return Completion(Normal, e.value());
2269 return e;
2270}
2271
2272void LabelNode::processVarDecls(ExecState *exec)
2273{
2274 statement->processVarDecls(exec);
2275}
2276
2277// ------------------------------ ThrowNode ------------------------------------
2278
2279// ECMA 12.13
2280Completion ThrowNode::execute(ExecState *exec)
2281{
2282 KJS_BREAKPOINT;
2283
2284 JSValue *v = expr->evaluate(exec);
2285 KJS_CHECKEXCEPTION
2286
2287 return Completion(Throw, v);
2288}
2289
2290// ------------------------------ TryNode --------------------------------------
2291
2292// ECMA 12.14
2293Completion TryNode::execute(ExecState *exec)
2294{
2295 KJS_BREAKPOINT;
2296
2297 Completion c = tryBlock->execute(exec);
2298
2299 if (catchBlock && c.complType() == Throw) {
2300 JSObject *obj = new JSObject;
2301 obj->put(exec, exceptionIdent, c.value(), DontDelete);
2302 exec->context().imp()->pushScope(obj);
2303 c = catchBlock->execute(exec);
2304 exec->context().imp()->popScope();
2305 }
2306
2307 if (finallyBlock) {
2308 Completion c2 = finallyBlock->execute(exec);
2309 if (c2.complType() != Normal)
2310 c = c2;
2311 }
2312
2313 return c;
2314}
2315
2316void TryNode::processVarDecls(ExecState *exec)
2317{
2318 tryBlock->processVarDecls(exec);
2319 if (catchBlock)
2320 catchBlock->processVarDecls(exec);
2321 if (finallyBlock)
2322 finallyBlock->processVarDecls(exec);
2323}
2324
2325// ------------------------------ ParameterNode --------------------------------
2326
2327// ECMA 13
2328JSValue *ParameterNode::evaluate(ExecState *)
2329{
2330 return jsUndefined();
2331}
2332
2333void ParameterNode::breakCycle()
2334{
2335 next = 0;
2336}
2337
2338// ------------------------------ FunctionBodyNode -----------------------------
2339
2340FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2341 : BlockNode(s)
2342 , m_sourceURL(Lexer::curr()->sourceURL())
2343 , m_sourceId(Parser::sid)
2344{
2345
2346 setLoc(-1, -1);
2347}
2348
2349void FunctionBodyNode::processFuncDecl(ExecState *exec)
2350{
2351 if (source)
2352 source->processFuncDecl(exec);
2353}
2354
2355// ------------------------------ FuncDeclNode ---------------------------------
2356
2357// ECMA 13
2358void FuncDeclNode::processFuncDecl(ExecState *exec)
2359{
2360 ContextImp *context = exec->context().imp();
2361
2362 // TODO: let this be an object with [[Class]] property "Function"
2363 FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
2364
2365 JSObject *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
2366 proto->put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2367 func->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2368
2369 int plen = 0;
2370 for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
2371 func->addParameter(p->ident());
2372
2373 func->put(exec, lengthPropertyName, jsNumber(plen), ReadOnly|DontDelete|DontEnum);
2374
2375 // ECMA 10.2.2
2376 context->variableObject()->put(exec, ident, func, Internal | (context->codeType() == EvalCode ? 0 : DontDelete));
2377
2378 if (body) {
2379 // hack the scope so that the function gets put as a property of func, and it's scope
2380 // contains the func as well as our current scope
2381 JSObject *oldVar = context->variableObject();
2382 context->setVariableObject(func);
2383 context->pushScope(func);
2384 body->processFuncDecl(exec);
2385 context->popScope();
2386 context->setVariableObject(oldVar);
2387 }
2388}
2389
2390Completion FuncDeclNode::execute(ExecState *)
2391{
2392 return Completion(Normal);
2393}
2394
2395// ------------------------------ FuncExprNode ---------------------------------
2396
2397// ECMA 13
2398JSValue *FuncExprNode::evaluate(ExecState *exec)
2399{
2400 ContextImp *context = exec->context().imp();
2401 bool named = !ident.isNull();
2402 JSObject *functionScopeObject = 0;
2403
2404 if (named) {
2405 // named FunctionExpressions can recursively call themselves,
2406 // but they won't register with the current scope chain and should
2407 // be contained as single property in an anonymous object.
2408 functionScopeObject = new JSObject;
2409 context->pushScope(functionScopeObject);
2410 }
2411
2412 FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
2413 JSObject *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
2414 proto->put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2415 func->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2416
2417 int plen = 0;
2418 for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
2419 func->addParameter(p->ident());
2420
2421 if (named) {
2422 functionScopeObject->put(exec, ident, func, Internal | ReadOnly | (context->codeType() == EvalCode ? 0 : DontDelete));
2423 context->popScope();
2424 }
2425
2426 return func;
2427}
2428
2429// ------------------------------ SourceElementsNode ---------------------------
2430
2431int SourceElementsNode::count = 0;
2432
2433SourceElementsNode::SourceElementsNode(StatementNode *s1)
2434 : node(s1), next(this)
2435{
2436 Parser::noteNodeCycle(this);
2437 setLoc(s1->firstLine(), s1->lastLine());
2438}
2439
2440SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
2441 : node(s2), next(s1->next)
2442{
2443 s1->next = this;
2444 setLoc(s1->firstLine(), s2->lastLine());
2445}
2446
2447// ECMA 14
2448Completion SourceElementsNode::execute(ExecState *exec)
2449{
2450 KJS_CHECKEXCEPTION
2451
2452 Completion c1 = node->execute(exec);
2453 KJS_CHECKEXCEPTION;
2454 if (c1.complType() != Normal)
2455 return c1;
2456
2457 for (SourceElementsNode *n = next.get(); n; n = n->next.get()) {
2458 Completion c2 = n->node->execute(exec);
2459 if (c2.complType() != Normal)
2460 return c2;
2461 // The spec says to return c2 here, but it seems that mozilla returns c1 if
2462 // c2 doesn't have a value
2463 if (c2.value())
2464 c1 = c2;
2465 }
2466
2467 return c1;
2468}
2469
2470// ECMA 14
2471void SourceElementsNode::processFuncDecl(ExecState *exec)
2472{
2473 for (SourceElementsNode *n = this; n; n = n->next.get())
2474 n->node->processFuncDecl(exec);
2475}
2476
2477void SourceElementsNode::processVarDecls(ExecState *exec)
2478{
2479 for (SourceElementsNode *n = this; n; n = n->next.get())
2480 n->node->processVarDecls(exec);
2481}
2482
2483void SourceElementsNode::breakCycle()
2484{
2485 next = 0;
2486}
2487
2488ProgramNode::ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s)
2489{
2490}
Note: See TracBrowser for help on using the repository browser.