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

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

JavaScriptCore:

Reviewed by Darin.

<rdar://problem/4283967> REGRESSION: 3% regression on PLT from new FastMalloc
http://bugzilla.opendarwin.org/show_bug.cgi?id=5243

A number of optimizations to the new threadsafe malloc that make it actually as fast
as dlmalloc (I measured wrong before) and as memory-efficient as the system malloc.

  • use fastMalloc for everything - it now gets applied to all new/delete allocations via a private inline operator new that is now included into every file via config.h.
  • tweaked some of the numeric parameters for size classes and amount of wasted memory allowed per allocation - this saves on memory use and consequently improves speed.
  • so long as the allocator is not being used on background threads, get the per-thread cache from a global variable instead of from pthread_getspecific, since the latter is slow.
  • inline more functions, and force the ones GCC refuses to inline with attribute(always_inline), nearly all of these have one call site so inlining them has to be a win.
  • use some tricks to calculate allocation size more efficiently and fewer times for small allocations, to avoid hitting the huge size table array.
  • avoid hitting the per-thread cache on code paths that don't need it.
  • implement inline assembly version of spinlock for PowerPC (was already done for x86)
  • bindings/NP_jsobject.cpp:
  • bindings/c/c_class.cpp:
  • bindings/c/c_instance.cpp:
  • bindings/c/c_runtime.cpp:
  • bindings/c/c_utility.cpp:
  • bindings/jni/jni_class.cpp:
  • bindings/jni/jni_instance.cpp:
  • bindings/jni/jni_jsobject.cpp:
  • bindings/jni/jni_objc.mm:
  • bindings/jni/jni_runtime.cpp:
  • bindings/jni/jni_utility.cpp:
  • bindings/npruntime.cpp:
  • bindings/objc/WebScriptObject.mm:
  • bindings/objc/objc_class.mm:
  • bindings/objc/objc_instance.mm:
  • bindings/objc/objc_runtime.mm:
  • bindings/objc/objc_utility.mm:
  • bindings/runtime.cpp:
  • bindings/runtime_array.cpp:
  • bindings/runtime_method.cpp:
  • bindings/runtime_object.cpp:
  • bindings/runtime_root.cpp:
  • bindings/testbindings.cpp:
  • bindings/testbindings.mm:
  • kjs/array_object.cpp: (ArrayInstanceImp::ArrayInstanceImp): (ArrayInstanceImp::~ArrayInstanceImp): (ArrayInstanceImp::resizeStorage):
  • kjs/bool_object.cpp:
  • kjs/collector.cpp: (KJS::Collector::registerThread):
  • kjs/config.h:
  • kjs/debugger.cpp:
  • kjs/error_object.cpp:
  • kjs/function.cpp:
  • kjs/function_object.cpp:
  • kjs/identifier.cpp: (KJS::Identifier::rehash):
  • kjs/internal.cpp: (KJS::Parser::saveNewNode): (KJS::clearNewNodes):
  • kjs/interpreter.cpp:
  • kjs/lexer.cpp: (Lexer::doneParsing): (Lexer::makeIdentifier): (Lexer::makeUString):
  • kjs/list.cpp:
  • kjs/math_object.cpp:
  • kjs/nodes.cpp:
  • kjs/nodes.h:
  • kjs/nodes2string.cpp:
  • kjs/number_object.cpp: (integer_part_noexp): (char_sequence):
  • kjs/object.cpp:
  • kjs/object_object.cpp:
  • kjs/property_map.cpp:
  • kjs/property_slot.cpp:
  • kjs/protected_values.cpp: (KJS::ProtectedValues::rehash):
  • kjs/reference.cpp:
  • kjs/reference_list.cpp:
  • kjs/regexp.cpp:
  • kjs/regexp_object.cpp:
  • kjs/scope_chain.cpp:
  • kjs/scope_chain.h:
  • kjs/string_object.cpp:
  • kjs/testkjs.cpp:
  • kjs/ustring.h:
  • kjs/value.cpp:
  • kxmlcore/Assertions.mm:
  • kxmlcore/FastMalloc.cpp: (KXMLCore::InitSizeClasses): (KXMLCore::DLL_IsEmpty): (KXMLCore::DLL_Prepend): (KXMLCore::TCMalloc_Central_FreeList::Insert): (KXMLCore::TCMalloc_Central_FreeList::Remove): (KXMLCore::TCMalloc_Central_FreeList::Populate): (KXMLCore::TCMalloc_ThreadCache::Allocate): (KXMLCore::TCMalloc_ThreadCache::FetchFromCentralCache): (KXMLCore::fastMallocRegisterThread): (KXMLCore::TCMalloc_ThreadCache::GetCache): (KXMLCore::TCMalloc_ThreadCache::GetCacheIfPresent): (KXMLCore::TCMalloc_ThreadCache::CreateCacheIfNecessary): (KXMLCore::do_malloc): (KXMLCore::do_free): (KXMLCore::realloc):
  • kxmlcore/FastMalloc.h: (operator new): (operator delete): (operator new[]): (operator delete[]):
  • kxmlcore/HashTable.cpp:
  • kxmlcore/TCSpinLock.h: (TCMalloc_SpinLock::Lock): (TCMalloc_SpinLock::Unlock): (TCMalloc_SlowLock):
  • kxmlcore/TCSystemAlloc.cpp:

WebCore:

Reviewed by Darin.

<rdar://problem/4283967> REGRESSION: 3% regression on PLT from new FastMalloc
http://bugzilla.opendarwin.org/show_bug.cgi?id=5243

  • use fastMalloc for everything - it now gets applied to all new/delete allocations via a private inline operator new that is now included into every file via config.h
  • WebCore.xcodeproj/project.pbxproj:
  • WebCorePrefix.h:
  • khtml/css/css_base.cpp:
  • khtml/css/css_base.h:
  • khtml/css/css_computedstyle.cpp:
  • khtml/css/css_ruleimpl.cpp:
  • khtml/css/css_stylesheetimpl.cpp:
  • khtml/css/css_valueimpl.cpp:
  • khtml/css/css_valueimpl.h:
  • khtml/css/csshelper.cpp:
  • khtml/css/cssparser.cpp: (ValueList::ValueList): (ValueList::~ValueList): (ValueList::addValue): (CSSParser::CSSParser): (CSSParser::~CSSParser): (CSSParser::setupParser): (CSSParser::addProperty):
  • khtml/css/cssstyleselector.cpp:
  • khtml/css/cssstyleselector.h:
  • khtml/dom/dom2_events.cpp:
  • khtml/dom/dom2_traversal.cpp:
  • khtml/dom/dom_misc.cpp:
  • khtml/dom/dom_string.cpp:
  • khtml/ecma/domparser.cpp:
  • khtml/ecma/kjs_binding.cpp:
  • khtml/ecma/kjs_css.cpp:
  • khtml/ecma/kjs_dom.cpp:
  • khtml/ecma/kjs_events.cpp:
  • khtml/ecma/kjs_html.cpp: (KJS::KJS::Context2DFunction::callAsFunction): (KJS::Gradient::~Gradient): (KJS::Gradient::addColorStop): (KJS::Gradient::colorStops):
  • khtml/ecma/kjs_navigator.cpp:
  • khtml/ecma/kjs_proxy.cpp:
  • khtml/ecma/kjs_range.cpp:
  • khtml/ecma/kjs_traversal.cpp:
  • khtml/ecma/kjs_views.cpp:
  • khtml/ecma/kjs_window.cpp:
  • khtml/ecma/xmlhttprequest.cpp:
  • khtml/ecma/xmlserializer.cpp:
  • khtml/editing/SelectionController.cpp:
  • khtml/editing/append_node_command.cpp:
  • khtml/editing/apply_style_command.cpp:
  • khtml/editing/break_blockquote_command.cpp:
  • khtml/editing/composite_edit_command.cpp:
  • khtml/editing/delete_from_text_node_command.cpp:
  • khtml/editing/delete_selection_command.cpp:
  • khtml/editing/edit_command.cpp:
  • khtml/editing/html_interchange.cpp:
  • khtml/editing/htmlediting.cpp:
  • khtml/editing/insert_into_text_node_command.cpp:
  • khtml/editing/insert_line_break_command.cpp:
  • khtml/editing/insert_node_before_command.cpp:
  • khtml/editing/insert_paragraph_separator_command.cpp:
  • khtml/editing/insert_text_command.cpp:
  • khtml/editing/join_text_nodes_command.cpp:
  • khtml/editing/jsediting.cpp:
  • khtml/editing/markup.cpp:
  • khtml/editing/merge_identical_elements_command.cpp:
  • khtml/editing/move_selection_command.cpp:
  • khtml/editing/rebalance_whitespace_command.cpp:
  • khtml/editing/remove_css_property_command.cpp:
  • khtml/editing/remove_node_attribute_command.cpp:
  • khtml/editing/remove_node_command.cpp:
  • khtml/editing/remove_node_preserving_children_command.cpp:
  • khtml/editing/replace_selection_command.cpp:
  • khtml/editing/set_node_attribute_command.cpp:
  • khtml/editing/split_element_command.cpp:
  • khtml/editing/split_text_node_command.cpp:
  • khtml/editing/split_text_node_containing_element.cpp:
  • khtml/editing/typing_command.cpp:
  • khtml/editing/visible_position.cpp:
  • khtml/editing/visible_range.cpp:
  • khtml/editing/visible_text.cpp: (khtml::CircularSearchBuffer::~CircularSearchBuffer): (khtml::CircularSearchBuffer::CircularSearchBuffer):
  • khtml/editing/visible_units.cpp:
  • khtml/editing/wrap_contents_in_dummy_span_command.cpp:
  • khtml/html/html_baseimpl.cpp:
  • khtml/html/html_blockimpl.cpp:
  • khtml/html/html_canvasimpl.cpp:
  • khtml/html/html_documentimpl.cpp:
  • khtml/html/html_elementimpl.cpp:
  • khtml/html/html_formimpl.cpp:
  • khtml/html/html_headimpl.cpp:
  • khtml/html/html_imageimpl.cpp:
  • khtml/html/html_inlineimpl.cpp:
  • khtml/html/html_listimpl.cpp:
  • khtml/html/html_miscimpl.cpp:
  • khtml/html/html_objectimpl.cpp:
  • khtml/html/html_tableimpl.cpp:
  • khtml/html/htmlfactory.cpp:
  • khtml/html/htmlnames.cpp:
  • khtml/html/htmlparser.cpp:
  • khtml/html/htmltokenizer.cpp: (khtml::HTMLTokenizer::enlargeBuffer): (khtml::HTMLTokenizer::enlargeScriptBuffer):
  • khtml/khtml_events.cpp:
  • khtml/khtml_part.cpp:
  • khtml/khtmlview.cpp:
  • khtml/misc/arena.cpp:
  • khtml/misc/arena.h:
  • khtml/misc/decoder.cpp:
  • khtml/misc/formdata.cpp:
  • khtml/misc/helper.cpp:
  • khtml/misc/loader.cpp:
  • khtml/misc/stringit.cpp:
  • khtml/rendering/bidi.cpp:
  • khtml/rendering/break_lines.cpp:
  • khtml/rendering/font.cpp:
  • khtml/rendering/render_arena.cpp:
  • khtml/rendering/render_block.cpp:
  • khtml/rendering/render_box.cpp:
  • khtml/rendering/render_br.cpp:
  • khtml/rendering/render_canvas.cpp:
  • khtml/rendering/render_canvasimage.cpp: (RenderCanvasImage::~RenderCanvasImage): (RenderCanvasImage::createDrawingContext):
  • khtml/rendering/render_container.cpp:
  • khtml/rendering/render_flexbox.cpp:
  • khtml/rendering/render_flow.cpp:
  • khtml/rendering/render_form.cpp:
  • khtml/rendering/render_frames.cpp:
  • khtml/rendering/render_image.cpp:
  • khtml/rendering/render_inline.cpp:
  • khtml/rendering/render_layer.cpp:
  • khtml/rendering/render_line.cpp:
  • khtml/rendering/render_list.cpp:
  • khtml/rendering/render_object.cpp:
  • khtml/rendering/render_replaced.cpp:
  • khtml/rendering/render_style.cpp:
  • khtml/rendering/render_style.h:
  • khtml/rendering/render_table.cpp:
  • khtml/rendering/render_text.cpp:
  • khtml/rendering/render_theme.cpp:
  • khtml/rendering/render_theme_mac.mm:
  • khtml/rendering/table_layout.cpp:
  • khtml/xbl/xbl_binding.cpp:
  • khtml/xbl/xbl_binding_manager.cpp:
  • khtml/xbl/xbl_docimpl.cpp:
  • khtml/xbl/xbl_protobinding.cpp:
  • khtml/xbl/xbl_protohandler.cpp:
  • khtml/xbl/xbl_protoimplementation.cpp:
  • khtml/xbl/xbl_tokenizer.cpp:
  • khtml/xml/EventNames.cpp:
  • khtml/xml/dom2_eventsimpl.cpp:
  • khtml/xml/dom2_eventsimpl.h:
  • khtml/xml/dom2_rangeimpl.cpp:
  • khtml/xml/dom2_rangeimpl.h:
  • khtml/xml/dom2_traversalimpl.cpp:
  • khtml/xml/dom2_traversalimpl.h:
  • khtml/xml/dom2_viewsimpl.cpp:
  • khtml/xml/dom2_viewsimpl.h:
  • khtml/xml/dom_atomicstring.cpp:
  • khtml/xml/dom_docimpl.cpp:
  • khtml/xml/dom_docimpl.h:
  • khtml/xml/dom_elementimpl.cpp:
  • khtml/xml/dom_elementimpl.h:
  • khtml/xml/dom_nodeimpl.cpp:
  • khtml/xml/dom_nodeimpl.h:
  • khtml/xml/dom_position.cpp:
  • khtml/xml/dom_qname.cpp:
  • khtml/xml/dom_stringimpl.cpp:
  • khtml/xml/dom_stringimpl.h:
  • khtml/xml/dom_textimpl.cpp:
  • khtml/xml/dom_xmlimpl.cpp:
  • khtml/xml/xml_tokenizer.cpp:
  • khtml/xsl/xsl_stylesheetimpl.cpp:
  • khtml/xsl/xslt_processorimpl.cpp:
  • kwq/DOM-CSS.mm:
  • kwq/DOM.mm:
  • kwq/DOMEvents.mm:
  • kwq/DOMHTML.mm:
  • kwq/DOMInternal.mm: (DOMString::DOMString):
  • kwq/DOMUtility.mm:
  • kwq/DOMViews.mm:
  • kwq/KWQAccObject.mm:
  • kwq/KWQAccObjectCache.mm:
  • kwq/KWQApplication.mm:
  • kwq/KWQArrayImpl.h:
  • kwq/KWQArrayImpl.mm:
  • kwq/KWQBuffer.mm:
  • kwq/KWQButton.mm:
  • kwq/KWQCString.mm:
  • kwq/KWQCharsets.mm:
  • kwq/KWQClipboard.mm:
  • kwq/KWQCollection.mm:
  • kwq/KWQColor.mm:
  • kwq/KWQComboBox.mm:
  • kwq/KWQCursor.mm:
  • kwq/KWQDateTime.mm:
  • kwq/KWQDictImpl.mm:
  • kwq/KWQEditCommand.mm:
  • kwq/KWQEvent.mm:
  • kwq/KWQExceptions.mm:
  • kwq/KWQFile.mm:
  • kwq/KWQFileButton.mm:
  • kwq/KWQFont.mm:
  • kwq/KWQFontFamily.h:
  • kwq/KWQFontFamily.mm:
  • kwq/KWQFontMetrics.mm:
  • kwq/KWQFormData.mm:
  • kwq/KWQFrame.mm:
  • kwq/KWQGlobal.mm:
  • kwq/KWQGuardedPtr.mm:
  • kwq/KWQKCharsets.mm:
  • kwq/KWQKConfigBase.mm:
  • kwq/KWQKCookieJar.mm:
  • kwq/KWQKCursor.mm:
  • kwq/KWQKGlobal.mm:
  • kwq/KWQKGlobalSettings.mm:
  • kwq/KWQKHTMLFactory.mm:
  • kwq/KWQKHTMLPart.cpp:
  • kwq/KWQKHTMLPart.mm:
  • kwq/KWQKHTMLPartBrowserExtension.mm:
  • kwq/KWQKHTMLView.mm:
  • kwq/KWQKHistoryProvider.mm:
  • kwq/KWQKJavaAppletWidget.mm:
  • kwq/KWQKJob.mm:
  • kwq/KWQKJobClasses.mm:
  • kwq/KWQKLocale.mm:
  • kwq/KWQKPartsBrowserInterface.mm:
  • kwq/KWQKPartsEvent.mm:
  • kwq/KWQKPartsPart.mm:
  • kwq/KWQKSSLKeyGen.mm:
  • kwq/KWQKStandardDirs.mm:
  • kwq/KWQKStringHandler.mm:
  • kwq/KWQKURL.mm: (KURL::KURL): (KURL::decode_string): (KURL::parse): (KURL::encode_string): (encodeRelativeString):
  • kwq/KWQKWin.mm:
  • kwq/KWQKWinModule.mm:
  • kwq/KWQLabel.mm:
  • kwq/KWQLineEdit.mm:
  • kwq/KWQListBox.mm:
  • kwq/KWQListImpl.mm:
  • kwq/KWQLoader.mm: (KWQIsResponseURLEqualToURL):
  • kwq/KWQMapImpl.h:
  • kwq/KWQMapImpl.mm:
  • kwq/KWQMovie.mm:
  • kwq/KWQObject.mm:
  • kwq/KWQPageState.mm:
  • kwq/KWQPaintDeviceMetrics.mm:
  • kwq/KWQPainter.mm:
  • kwq/KWQPalette.mm:
  • kwq/KWQPen.mm:
  • kwq/KWQPixmap.mm:
  • kwq/KWQPoint.mm:
  • kwq/KWQPointArray.mm:
  • kwq/KWQPtrDictImpl.mm:
  • kwq/KWQPushButton.mm:
  • kwq/KWQRect.mm:
  • kwq/KWQRegExp.mm:
  • kwq/KWQRegion.mm:
  • kwq/KWQRenderTreeDebug.cpp:
  • kwq/KWQResourceLoader.mm:
  • kwq/KWQScrollBar.mm:
  • kwq/KWQScrollView.mm:
  • kwq/KWQSignal.mm:
  • kwq/KWQSignalStubs.mm:
  • kwq/KWQSize.mm:
  • kwq/KWQSlider.mm:
  • kwq/KWQSlot.mm:
  • kwq/KWQString.h:
  • kwq/KWQString.mm: (ALLOC_CHAR): (REALLOC_CHAR): (DELETE_CHAR): (ALLOC_QCHAR): (REALLOC_QCHAR): (DELETE_QCHAR): (_printQStringAllocationStatistics): (allocateHandle): (KWQStringData::operator new): (KWQStringData::operator delete): (freeHandle):
  • kwq/KWQStringList.mm:
  • kwq/KWQStyle.mm:
  • kwq/KWQTextArea.mm:
  • kwq/KWQTextCodec.mm:
  • kwq/KWQTextEdit.mm:
  • kwq/KWQTextField.mm:
  • kwq/KWQTextStream.mm:
  • kwq/KWQTextUtilities.mm:
  • kwq/KWQTimer.mm:
  • kwq/KWQValueListImpl.h:
  • kwq/KWQValueListImpl.mm:
  • kwq/KWQVariant.mm:
  • kwq/KWQVectorImpl.mm: (KWQVectorImpl::KWQVectorImpl): (KWQVectorImpl::~KWQVectorImpl): (KWQVectorImpl::clear): (KWQVectorImpl::resize): (KWQVectorImpl::assign):
  • kwq/KWQWMatrix.mm:
  • kwq/KWQWidget.mm:
  • kwq/KWQWindowWidget.mm:
  • kwq/WebCoreBridge.mm:
  • kwq/WebCoreCache.mm:
  • kwq/WebCoreEncodings.mm:
  • kwq/WebCoreJavaScript.mm:
  • kwq/WebCoreScriptDebugger.mm:
  • kwq/WebCoreSettings.mm:
  • kwq/WebCoreTextRendererFactory.mm:
  • kwq/can-convert.mm:
  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 61.0 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 Steet, 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#include <assert.h>
29#ifdef KJS_DEBUG_MEM
30#include <stdio.h>
31#include <typeinfo>
32#endif
33
34#include "collector.h"
35#include "context.h"
36#include "debugger.h"
37#include "function_object.h"
38#include "internal.h"
39#include "value.h"
40#include "object.h"
41#include "types.h"
42#include "interpreter.h"
43#include "lexer.h"
44#include "operations.h"
45#include "ustring.h"
46#include "reference_list.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 ValueImp *ex = exec->exception(); \
64 exec->clearException(); \
65 return Completion(Throw, ex); \
66 } \
67 if (Collector::outOfMemory()) \
68 return Completion(Throw, Error::create(exec, GeneralError, "Out of memory"));
69
70#define KJS_CHECKEXCEPTIONVALUE \
71 if (exec->hadException()) { \
72 setExceptionDetailsIfNeeded(exec); \
73 return Undefined(); \
74 } \
75 if (Collector::outOfMemory()) \
76 return Undefined(); // will be picked up by KJS_CHECKEXCEPTION
77
78#define KJS_CHECKEXCEPTIONLIST \
79 if (exec->hadException()) { \
80 setExceptionDetailsIfNeeded(exec); \
81 return List(); \
82 } \
83 if (Collector::outOfMemory()) \
84 return List(); // will be picked up by KJS_CHECKEXCEPTION
85
86// ------------------------------ Node -----------------------------------------
87
88Node::Node()
89{
90 line = Lexer::curr()->lineNo();
91 sourceURL = Lexer::curr()->sourceURL();
92 m_refcount = 0;
93 Parser::saveNewNode(this);
94}
95
96Node::~Node()
97{
98}
99
100static void substitute(UString &string, const UString &substring)
101{
102 int position = string.find("%s");
103 assert(position != -1);
104 string = string.substr(0, position) + substring + string.substr(position + 2);
105}
106
107Completion Node::createErrorCompletion(ExecState *exec, ErrorType e, const char *msg)
108{
109 return Completion(Throw, Error::create(exec, e, msg, lineNo(), sourceId(), &sourceURL));
110}
111
112Completion Node::createErrorCompletion(ExecState *exec, ErrorType e, const char *msg, const Identifier &ident)
113{
114 UString message = msg;
115 substitute(message, ident.ustring());
116 return Completion(Throw, Error::create(exec, e, message, lineNo(), sourceId(), &sourceURL));
117}
118
119ValueImp *Node::throwError(ExecState *exec, ErrorType e, const char *msg)
120{
121 return KJS::throwError(exec, e, msg, lineNo(), sourceId(), &sourceURL);
122}
123
124ValueImp *Node::throwError(ExecState *exec, ErrorType e, const char *msg, ValueImp *v, Node *expr)
125{
126 UString message = msg;
127 substitute(message, v->toString(exec));
128 substitute(message, expr->toString());
129 return KJS::throwError(exec, e, message, lineNo(), sourceId(), &sourceURL);
130}
131
132
133ValueImp *Node::throwError(ExecState *exec, ErrorType e, const char *msg, const Identifier &label)
134{
135 UString message = msg;
136 substitute(message, label.ustring());
137 return KJS::throwError(exec, e, message, lineNo(), sourceId(), &sourceURL);
138}
139
140ValueImp *Node::throwError(ExecState *exec, ErrorType e, const char *msg, ValueImp *v, Node *e1, Node *e2)
141{
142 UString message = msg;
143 substitute(message, v->toString(exec));
144 substitute(message, e1->toString());
145 substitute(message, e2->toString());
146 return KJS::throwError(exec, e, message, lineNo(), sourceId(), &sourceURL);
147}
148
149ValueImp *Node::throwError(ExecState *exec, ErrorType e, const char *msg, ValueImp *v, Node *expr, const Identifier &label)
150{
151 UString message = msg;
152 substitute(message, v->toString(exec));
153 substitute(message, expr->toString());
154 substitute(message, label.ustring());
155 return KJS::throwError(exec, e, message, lineNo(), sourceId(), &sourceURL);
156}
157
158ValueImp *Node::throwError(ExecState *exec, ErrorType e, const char *msg, ValueImp *v, const Identifier &label)
159{
160 UString message = msg;
161 substitute(message, v->toString(exec));
162 substitute(message, label.ustring());
163 return KJS::throwError(exec, e, message, lineNo(), sourceId(), &sourceURL);
164}
165
166ValueImp *Node::throwUndefinedVariableError(ExecState *exec, const Identifier &ident)
167{
168 return throwError(exec, ReferenceError, "Can't find variable: %s", ident);
169}
170
171void Node::setExceptionDetailsIfNeeded(ExecState *exec)
172{
173 ValueImp *exceptionValue = exec->exception();
174 if (exceptionValue->isObject()) {
175 ObjectImp *exception = static_cast<ObjectImp *>(exceptionValue);
176 if (!exception->hasProperty(exec, "line") && !exception->hasProperty(exec, "sourceURL")) {
177 exception->put(exec, "line", Number(line));
178 exception->put(exec, "sourceURL", String(sourceURL));
179 }
180 }
181}
182
183Node *Node::nodeInsideAllParens()
184{
185 return this;
186}
187
188// ------------------------------ StatementNode --------------------------------
189
190StatementNode::StatementNode() : l0(-1), l1(-1), sid(-1), breakPoint(false)
191{
192}
193
194void StatementNode::setLoc(int line0, int line1, int sourceId)
195{
196 l0 = line0;
197 l1 = line1;
198 sid = sourceId;
199}
200
201// return true if the debugger wants us to stop at this point
202bool StatementNode::hitStatement(ExecState *exec)
203{
204 Debugger *dbg = exec->dynamicInterpreter()->imp()->debugger();
205 if (dbg)
206 return dbg->atStatement(exec,sid,l0,l1);
207 else
208 return true; // continue
209}
210
211void StatementNode::processFuncDecl(ExecState *exec)
212{
213}
214
215// ------------------------------ NullNode -------------------------------------
216
217ValueImp *NullNode::evaluate(ExecState *)
218{
219 return Null();
220}
221
222// ------------------------------ BooleanNode ----------------------------------
223
224ValueImp *BooleanNode::evaluate(ExecState *)
225{
226 return jsBoolean(value);
227}
228
229// ------------------------------ NumberNode -----------------------------------
230
231ValueImp *NumberNode::evaluate(ExecState *)
232{
233 return jsNumber(value);
234}
235
236// ------------------------------ StringNode -----------------------------------
237
238ValueImp *StringNode::evaluate(ExecState *)
239{
240 return jsString(value);
241}
242
243// ------------------------------ RegExpNode -----------------------------------
244
245ValueImp *RegExpNode::evaluate(ExecState *exec)
246{
247 List list;
248 list.append(jsString(pattern));
249 list.append(jsString(flags));
250
251 ObjectImp *reg = exec->lexicalInterpreter()->imp()->builtinRegExp();
252 return reg->construct(exec,list);
253}
254
255// ------------------------------ ThisNode -------------------------------------
256
257// ECMA 11.1.1
258ValueImp *ThisNode::evaluate(ExecState *exec)
259{
260 return exec->context().imp()->thisValue();
261}
262
263// ------------------------------ ResolveNode ----------------------------------
264
265// ECMA 11.1.2 & 10.1.4
266ValueImp *ResolveNode::evaluate(ExecState *exec)
267{
268 const ScopeChain& chain = exec->context().imp()->scopeChain();
269 ScopeChainIterator iter = chain.begin();
270 ScopeChainIterator end = chain.end();
271
272 // we must always have something in the scope chain
273 assert(iter != end);
274
275 PropertySlot slot;
276 do {
277 ObjectImp *o = *iter;
278
279 if (o->getPropertySlot(exec, ident, slot))
280 return slot.getValue(exec, ident);
281
282 ++iter;
283 } while (iter != end);
284
285 return throwUndefinedVariableError(exec, ident);
286}
287
288// ------------------------------ GroupNode ------------------------------------
289
290// ECMA 11.1.6
291ValueImp *GroupNode::evaluate(ExecState *exec)
292{
293 return group->evaluate(exec);
294}
295
296Node *GroupNode::nodeInsideAllParens()
297{
298 Node *n = this;
299 do
300 n = static_cast<GroupNode *>(n)->group.get();
301 while (n->isGroupNode());
302 return n;
303}
304
305// ------------------------------ ElementNode ----------------------------------
306
307// ECMA 11.1.4
308ValueImp *ElementNode::evaluate(ExecState *exec)
309{
310 ObjectImp *array = exec->lexicalInterpreter()->builtinArray()->construct(exec, List::empty());
311 int length = 0;
312 for (ElementNode *n = this; n; n = n->list.get()) {
313 ValueImp *val = n->node->evaluate(exec);
314 KJS_CHECKEXCEPTIONVALUE
315 length += n->elision;
316 array->put(exec, length++, val);
317 }
318 return array;
319}
320
321// ------------------------------ ArrayNode ------------------------------------
322
323// ECMA 11.1.4
324ValueImp *ArrayNode::evaluate(ExecState *exec)
325{
326 ObjectImp *array;
327 int length;
328
329 if (element) {
330 array = static_cast<ObjectImp*>(element->evaluate(exec));
331 KJS_CHECKEXCEPTIONVALUE
332 length = opt ? array->get(exec,lengthPropertyName)->toInt32(exec) : 0;
333 } else {
334 ValueImp *newArr = exec->lexicalInterpreter()->builtinArray()->construct(exec,List::empty());
335 array = static_cast<ObjectImp*>(newArr);
336 length = 0;
337 }
338
339 if (opt)
340 array->put(exec,lengthPropertyName, jsNumber(elision + length), DontEnum | DontDelete);
341
342 return array;
343}
344
345// ------------------------------ ObjectLiteralNode ----------------------------
346
347// ECMA 11.1.5
348ValueImp *ObjectLiteralNode::evaluate(ExecState *exec)
349{
350 if (list)
351 return list->evaluate(exec);
352
353 return exec->lexicalInterpreter()->builtinObject()->construct(exec,List::empty());
354}
355
356// ------------------------------ PropertyValueNode ----------------------------
357
358// ECMA 11.1.5
359ValueImp *PropertyValueNode::evaluate(ExecState *exec)
360{
361 ObjectImp *obj = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
362
363 for (PropertyValueNode *p = this; p; p = p->list.get()) {
364 ValueImp *n = p->name->evaluate(exec);
365 KJS_CHECKEXCEPTIONVALUE
366 ValueImp *v = p->assign->evaluate(exec);
367 KJS_CHECKEXCEPTIONVALUE
368
369 obj->put(exec, Identifier(n->toString(exec)), v);
370 }
371
372 return obj;
373}
374
375// ------------------------------ PropertyNode ---------------------------------
376
377// ECMA 11.1.5
378ValueImp *PropertyNode::evaluate(ExecState *)
379{
380 ValueImp *s;
381
382 if (str.isNull()) {
383 s = String(UString::from(numeric));
384 } else {
385 s = String(str.ustring());
386 }
387
388 return s;
389}
390
391// ------------------------------ BracketAccessorNode --------------------------------
392
393// ECMA 11.2.1a
394ValueImp *BracketAccessorNode::evaluate(ExecState *exec)
395{
396 ValueImp *v1 = expr1->evaluate(exec);
397 KJS_CHECKEXCEPTIONVALUE
398 ValueImp *v2 = expr2->evaluate(exec);
399 KJS_CHECKEXCEPTIONVALUE
400 ObjectImp *o = v1->toObject(exec);
401 uint32_t i;
402 if (v2->getUInt32(i))
403 return o->get(exec, i);
404 return o->get(exec, Identifier(v2->toString(exec)));
405}
406
407// ------------------------------ DotAccessorNode --------------------------------
408
409// ECMA 11.2.1b
410ValueImp *DotAccessorNode::evaluate(ExecState *exec)
411{
412 ValueImp *v = expr->evaluate(exec);
413 KJS_CHECKEXCEPTIONVALUE
414 return v->toObject(exec)->get(exec, ident);
415
416}
417
418// ------------------------------ ArgumentListNode -----------------------------
419
420ValueImp *ArgumentListNode::evaluate(ExecState *)
421{
422 assert(0);
423 return 0; // dummy, see evaluateList()
424}
425
426// ECMA 11.2.4
427List ArgumentListNode::evaluateList(ExecState *exec)
428{
429 List l;
430
431 for (ArgumentListNode *n = this; n; n = n->list.get()) {
432 ValueImp *v = n->expr->evaluate(exec);
433 KJS_CHECKEXCEPTIONLIST
434 l.append(v);
435 }
436
437 return l;
438}
439
440// ------------------------------ ArgumentsNode --------------------------------
441
442ValueImp *ArgumentsNode::evaluate(ExecState *)
443{
444 assert(0);
445 return 0; // dummy, see evaluateList()
446}
447
448// ECMA 11.2.4
449List ArgumentsNode::evaluateList(ExecState *exec)
450{
451 if (!list)
452 return List();
453
454 return list->evaluateList(exec);
455}
456
457// ------------------------------ NewExprNode ----------------------------------
458
459// ECMA 11.2.2
460
461ValueImp *NewExprNode::evaluate(ExecState *exec)
462{
463 ValueImp *v = expr->evaluate(exec);
464 KJS_CHECKEXCEPTIONVALUE
465
466 List argList;
467 if (args) {
468 argList = args->evaluateList(exec);
469 KJS_CHECKEXCEPTIONVALUE
470 }
471
472 if (!v->isObject()) {
473 return throwError(exec, TypeError, "Value %s (result of expression %s) is not an object. Cannot be used with new.", v, expr.get());
474 }
475
476 ObjectImp *constr = static_cast<ObjectImp*>(v);
477 if (!constr->implementsConstruct()) {
478 return throwError(exec, TypeError, "Value %s (result of expression %s) is not a constructor. Cannot be used with new.", v, expr.get());
479 }
480
481 return constr->construct(exec, argList);
482}
483
484// ECMA 11.2.3
485ValueImp *FunctionCallValueNode::evaluate(ExecState *exec)
486{
487 ValueImp *v = expr->evaluate(exec);
488 KJS_CHECKEXCEPTIONVALUE
489
490 if (!v->isObject()) {
491 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, expr.get());
492 }
493
494 ObjectImp *func = static_cast<ObjectImp*>(v);
495
496 if (!func->implementsCall()) {
497 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, expr.get());
498 }
499
500 List argList = args->evaluateList(exec);
501 KJS_CHECKEXCEPTIONVALUE
502
503 ObjectImp *thisObj = exec->dynamicInterpreter()->globalObject();
504
505 return func->call(exec, thisObj, argList);
506}
507
508// ECMA 11.2.3
509ValueImp *FunctionCallResolveNode::evaluate(ExecState *exec)
510{
511 const ScopeChain& chain = exec->context().imp()->scopeChain();
512 ScopeChainIterator iter = chain.begin();
513 ScopeChainIterator end = chain.end();
514
515 // we must always have something in the scope chain
516 assert(iter != end);
517
518 PropertySlot slot;
519 ObjectImp *base;
520 do {
521 base = *iter;
522 if (base->getPropertySlot(exec, ident, slot)) {
523 ValueImp *v = slot.getValue(exec, ident);
524 KJS_CHECKEXCEPTIONVALUE
525
526 if (!v->isObject()) {
527 return throwError(exec, TypeError, "Value %s (result of expression %s) is not object.", v, ident);
528 }
529
530 ObjectImp *func = static_cast<ObjectImp*>(v);
531
532 if (!func->implementsCall()) {
533 return throwError(exec, TypeError, "Object %s (result of expression %s) does not allow calls.", v, ident);
534 }
535
536 List argList = args->evaluateList(exec);
537 KJS_CHECKEXCEPTIONVALUE
538
539 ObjectImp *thisObj = base;
540 // ECMA 11.2.3 says that in this situation the this value should be null.
541 // However, section 10.2.3 says that in the case where the value provided
542 // by the caller is null, the global object should be used. It also says
543 // that the section does not apply to interal functions, but for simplicity
544 // of implementation we use the global object anyway here. This guarantees
545 // that in host objects you always get a valid object for this.
546 if (thisObj->isActivation())
547 thisObj = exec->dynamicInterpreter()->globalObject();
548
549 return func->call(exec, thisObj, argList);
550 }
551 ++iter;
552 } while (iter != end);
553
554 return throwUndefinedVariableError(exec, ident);
555}
556
557// ECMA 11.2.3
558ValueImp *FunctionCallBracketNode::evaluate(ExecState *exec)
559{
560 ValueImp *baseVal = base->evaluate(exec);
561 KJS_CHECKEXCEPTIONVALUE
562
563 ValueImp *subscriptVal = subscript->evaluate(exec);
564
565 ObjectImp *baseObj = baseVal->toObject(exec);
566 uint32_t i;
567 PropertySlot slot;
568
569 ValueImp *funcVal;
570 if (subscriptVal->getUInt32(i)) {
571 if (baseObj->getPropertySlot(exec, i, slot))
572 funcVal = slot.getValue(exec, i);
573 else
574 funcVal = Undefined();
575 } else {
576 Identifier ident(subscriptVal->toString(exec));
577 if (baseObj->getPropertySlot(exec, ident, slot))
578 funcVal = baseObj->get(exec, ident);
579 else
580 funcVal = Undefined();
581 }
582
583 KJS_CHECKEXCEPTIONVALUE
584
585 if (!funcVal->isObject()) {
586 return throwError(exec, TypeError, "Value %s (result of expression %s[%s]) is not object.", funcVal, base.get(), subscript.get());
587 }
588
589 ObjectImp *func = static_cast<ObjectImp*>(funcVal);
590
591 if (!func->implementsCall()) {
592 return throwError(exec, TypeError, "Object %s (result of expression %s[%s]) does not allow calls.", funcVal, base.get(), subscript.get());
593 }
594
595 List argList = args->evaluateList(exec);
596 KJS_CHECKEXCEPTIONVALUE
597
598 ObjectImp *thisObj = baseObj;
599 assert(thisObj);
600 assert(thisObj->isObject());
601 assert(!thisObj->isActivation());
602
603 return func->call(exec, thisObj, argList);
604}
605
606static const char *dotExprNotAnObjectString()
607{
608 return "Value %s (result of expression %s.%s) is not object.";
609}
610
611static const char *dotExprDoesNotAllowCallsString()
612{
613 return "Object %s (result of expression %s.%s) does not allow calls.";
614}
615
616// ECMA 11.2.3
617ValueImp *FunctionCallDotNode::evaluate(ExecState *exec)
618{
619 ValueImp *baseVal = base->evaluate(exec);
620
621 ObjectImp *baseObj = baseVal->toObject(exec);
622 PropertySlot slot;
623 ValueImp *funcVal = baseObj->getPropertySlot(exec, ident, slot) ? slot.getValue(exec, ident) : Undefined();
624 KJS_CHECKEXCEPTIONVALUE
625
626 if (!funcVal->isObject())
627 return throwError(exec, TypeError, dotExprNotAnObjectString(), funcVal, base.get(), ident);
628
629 ObjectImp *func = static_cast<ObjectImp*>(funcVal);
630
631 if (!func->implementsCall())
632 return throwError(exec, TypeError, dotExprDoesNotAllowCallsString(), funcVal, base.get(), ident);
633
634 List argList = args->evaluateList(exec);
635 KJS_CHECKEXCEPTIONVALUE
636
637 ObjectImp *thisObj = baseObj;
638 assert(thisObj);
639 assert(thisObj->isObject());
640 assert(!thisObj->isActivation());
641
642 return func->call(exec, thisObj, argList);
643}
644
645// ECMA 11.3
646
647// ------------------------------ PostfixResolveNode ----------------------------------
648
649ValueImp *PostfixResolveNode::evaluate(ExecState *exec)
650{
651 const ScopeChain& chain = exec->context().imp()->scopeChain();
652 ScopeChainIterator iter = chain.begin();
653 ScopeChainIterator end = chain.end();
654
655 // we must always have something in the scope chain
656 assert(iter != end);
657
658 PropertySlot slot;
659 ObjectImp *base;
660 do {
661 base = *iter;
662 if (base->getPropertySlot(exec, m_ident, slot)) {
663 ValueImp *v = slot.getValue(exec, m_ident);
664
665 bool knownToBeInteger;
666 double n = v->toNumber(exec, knownToBeInteger);
667
668 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
669 base->put(exec, m_ident, jsNumber(newValue, knownToBeInteger));
670
671 return jsNumber(n, knownToBeInteger);
672 }
673
674 ++iter;
675 } while (iter != end);
676
677 return throwUndefinedVariableError(exec, m_ident);
678}
679
680// ------------------------------ PostfixBracketNode ----------------------------------
681
682ValueImp *PostfixBracketNode::evaluate(ExecState *exec)
683{
684 ValueImp *baseValue = m_base->evaluate(exec);
685 KJS_CHECKEXCEPTIONVALUE
686 ValueImp *subscript = m_subscript->evaluate(exec);
687 KJS_CHECKEXCEPTIONVALUE
688
689 ObjectImp *base = baseValue->toObject(exec);
690
691 uint32_t propertyIndex;
692 if (subscript->getUInt32(propertyIndex)) {
693 PropertySlot slot;
694 ValueImp *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, propertyIndex) : Undefined();
695 KJS_CHECKEXCEPTIONVALUE
696
697 bool knownToBeInteger;
698 double n = v->toNumber(exec, knownToBeInteger);
699
700 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
701 base->put(exec, propertyIndex, jsNumber(newValue, knownToBeInteger));
702
703 return jsNumber(n, knownToBeInteger);
704 }
705
706 Identifier propertyName(subscript->toString(exec));
707 PropertySlot slot;
708 ValueImp *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, propertyName) : Undefined();
709 KJS_CHECKEXCEPTIONVALUE
710
711 bool knownToBeInteger;
712 double n = v->toNumber(exec, knownToBeInteger);
713
714 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
715 base->put(exec, propertyName, jsNumber(newValue, knownToBeInteger));
716
717 return jsNumber(n, knownToBeInteger);
718}
719
720// ------------------------------ PostfixDotNode ----------------------------------
721
722ValueImp *PostfixDotNode::evaluate(ExecState *exec)
723{
724 ValueImp *baseValue = m_base->evaluate(exec);
725 KJS_CHECKEXCEPTIONVALUE
726 ObjectImp *base = baseValue->toObject(exec);
727
728 PropertySlot slot;
729 ValueImp *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : Undefined();
730 KJS_CHECKEXCEPTIONVALUE
731
732 bool knownToBeInteger;
733 double n = v->toNumber(exec, knownToBeInteger);
734
735 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
736 base->put(exec, m_ident, jsNumber(newValue, knownToBeInteger));
737
738 return jsNumber(n, knownToBeInteger);
739}
740
741// ECMA 11.4.1
742
743// ------------------------------ DeleteResolveNode -----------------------------------
744ValueImp *DeleteResolveNode::evaluate(ExecState *exec)
745{
746 const ScopeChain& chain = exec->context().imp()->scopeChain();
747 ScopeChainIterator iter = chain.begin();
748 ScopeChainIterator end = chain.end();
749
750 // we must always have something in the scope chain
751 assert(iter != end);
752
753 PropertySlot slot;
754 ObjectImp *base;
755 do {
756 base = *iter;
757 if (base->getPropertySlot(exec, m_ident, slot)) {
758 return jsBoolean(base->deleteProperty(exec, m_ident));
759 }
760
761 ++iter;
762 } while (iter != end);
763
764 return jsBoolean(true);
765}
766
767// ------------------------------ DeleteBracketNode -----------------------------------
768ValueImp *DeleteBracketNode::evaluate(ExecState *exec)
769{
770 ValueImp *baseValue = m_base->evaluate(exec);
771 KJS_CHECKEXCEPTIONVALUE
772 ValueImp *subscript = m_subscript->evaluate(exec);
773 KJS_CHECKEXCEPTIONVALUE
774
775 ObjectImp *base = baseValue->toObject(exec);
776
777 uint32_t propertyIndex;
778 if (subscript->getUInt32(propertyIndex))
779 return jsBoolean(base->deleteProperty(exec, propertyIndex));
780
781 Identifier propertyName(subscript->toString(exec));
782 return jsBoolean(base->deleteProperty(exec, propertyName));
783}
784
785// ------------------------------ DeleteDotNode -----------------------------------
786ValueImp *DeleteDotNode::evaluate(ExecState *exec)
787{
788 ValueImp *baseValue = m_base->evaluate(exec);
789 ObjectImp *base = baseValue->toObject(exec);
790 KJS_CHECKEXCEPTIONVALUE
791
792 return jsBoolean(base->deleteProperty(exec, m_ident));
793}
794
795// ------------------------------ DeleteValueNode -----------------------------------
796ValueImp *DeleteValueNode::evaluate(ExecState *exec)
797{
798 m_expr->evaluate(exec);
799 KJS_CHECKEXCEPTIONVALUE
800
801 // delete on a non-location expression ignores the value and returns true
802 return jsBoolean(true);
803}
804
805// ------------------------------ VoidNode -------------------------------------
806
807// ECMA 11.4.2
808ValueImp *VoidNode::evaluate(ExecState *exec)
809{
810 expr->evaluate(exec);
811 KJS_CHECKEXCEPTIONVALUE
812
813 return Undefined();
814}
815
816// ECMA 11.4.3
817
818// ------------------------------ TypeOfValueNode -----------------------------------
819
820static ValueImp *typeStringForValue(ValueImp *v)
821{
822 switch (v->type()) {
823 case UndefinedType:
824 return jsString("undefined");
825 case NullType:
826 return jsString("object");
827 case BooleanType:
828 return jsString("boolean");
829 case NumberType:
830 return jsString("number");
831 case StringType:
832 return jsString("string");
833 default:
834 if (v->isObject() && static_cast<ObjectImp*>(v)->implementsCall())
835 return jsString("function");
836 else
837 return jsString("object");
838 }
839}
840
841ValueImp *TypeOfResolveNode::evaluate(ExecState *exec)
842{
843 const ScopeChain& chain = exec->context().imp()->scopeChain();
844 ScopeChainIterator iter = chain.begin();
845 ScopeChainIterator end = chain.end();
846
847 // we must always have something in the scope chain
848 assert(iter != end);
849
850 PropertySlot slot;
851 ObjectImp *base;
852 do {
853 base = *iter;
854 if (base->getPropertySlot(exec, m_ident, slot)) {
855 ValueImp *v = slot.getValue(exec, m_ident);
856 return typeStringForValue(v);
857 }
858
859 ++iter;
860 } while (iter != end);
861
862 return jsString("undefined");
863}
864
865// ------------------------------ TypeOfValueNode -----------------------------------
866
867ValueImp *TypeOfValueNode::evaluate(ExecState *exec)
868{
869 ValueImp *v = m_expr->evaluate(exec);
870 KJS_CHECKEXCEPTIONVALUE
871
872 return typeStringForValue(v);
873}
874
875// ECMA 11.4.4 and 11.4.5
876
877// ------------------------------ PrefixResolveNode ----------------------------------
878
879ValueImp *PrefixResolveNode::evaluate(ExecState *exec)
880{
881 const ScopeChain& chain = exec->context().imp()->scopeChain();
882 ScopeChainIterator iter = chain.begin();
883 ScopeChainIterator end = chain.end();
884
885 // we must always have something in the scope chain
886 assert(iter != end);
887
888 PropertySlot slot;
889 ObjectImp *base;
890 do {
891 base = *iter;
892 if (base->getPropertySlot(exec, m_ident, slot)) {
893 ValueImp *v = slot.getValue(exec, m_ident);
894
895 bool knownToBeInteger;
896 double n = v->toNumber(exec, knownToBeInteger);
897
898 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
899 ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
900 base->put(exec, m_ident, n2);
901
902 return n2;
903 }
904
905 ++iter;
906 } while (iter != end);
907
908 return throwUndefinedVariableError(exec, m_ident);
909}
910
911// ------------------------------ PrefixBracketNode ----------------------------------
912
913ValueImp *PrefixBracketNode::evaluate(ExecState *exec)
914{
915 ValueImp *baseValue = m_base->evaluate(exec);
916 KJS_CHECKEXCEPTIONVALUE
917 ValueImp *subscript = m_subscript->evaluate(exec);
918 KJS_CHECKEXCEPTIONVALUE
919
920 ObjectImp *base = baseValue->toObject(exec);
921
922 uint32_t propertyIndex;
923 if (subscript->getUInt32(propertyIndex)) {
924 PropertySlot slot;
925 ValueImp *v = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, propertyIndex) : Undefined();
926 KJS_CHECKEXCEPTIONVALUE
927
928 bool knownToBeInteger;
929 double n = v->toNumber(exec, knownToBeInteger);
930
931 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
932 ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
933 base->put(exec, propertyIndex, n2);
934
935 return n2;
936 }
937
938 Identifier propertyName(subscript->toString(exec));
939 PropertySlot slot;
940 ValueImp *v = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, propertyName) : Undefined();
941 KJS_CHECKEXCEPTIONVALUE
942
943 bool knownToBeInteger;
944 double n = v->toNumber(exec, knownToBeInteger);
945
946 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
947 ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
948 base->put(exec, propertyName, n2);
949
950 return n2;
951}
952
953// ------------------------------ PrefixDotNode ----------------------------------
954
955ValueImp *PrefixDotNode::evaluate(ExecState *exec)
956{
957 ValueImp *baseValue = m_base->evaluate(exec);
958 KJS_CHECKEXCEPTIONVALUE
959 ObjectImp *base = baseValue->toObject(exec);
960
961 PropertySlot slot;
962 ValueImp *v = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : Undefined();
963 KJS_CHECKEXCEPTIONVALUE
964
965 bool knownToBeInteger;
966 double n = v->toNumber(exec, knownToBeInteger);
967
968 double newValue = (m_oper == OpPlusPlus) ? n + 1 : n - 1;
969 ValueImp *n2 = jsNumber(newValue, knownToBeInteger);
970 base->put(exec, m_ident, n2);
971
972 return n2;
973}
974
975// ------------------------------ UnaryPlusNode --------------------------------
976
977// ECMA 11.4.6
978ValueImp *UnaryPlusNode::evaluate(ExecState *exec)
979{
980 ValueImp *v = expr->evaluate(exec);
981 KJS_CHECKEXCEPTIONVALUE
982
983 return jsNumber(v->toNumber(exec));
984}
985
986// ------------------------------ NegateNode -----------------------------------
987
988// ECMA 11.4.7
989ValueImp *NegateNode::evaluate(ExecState *exec)
990{
991 ValueImp *v = expr->evaluate(exec);
992 KJS_CHECKEXCEPTIONVALUE
993
994 bool knownToBeInteger;
995 double n = v->toNumber(exec, knownToBeInteger);
996 return jsNumber(-n, knownToBeInteger && n != 0);
997}
998
999// ------------------------------ BitwiseNotNode -------------------------------
1000
1001// ECMA 11.4.8
1002ValueImp *BitwiseNotNode::evaluate(ExecState *exec)
1003{
1004 ValueImp *v = expr->evaluate(exec);
1005 KJS_CHECKEXCEPTIONVALUE
1006 return jsNumber(~v->toInt32(exec));
1007}
1008
1009// ------------------------------ LogicalNotNode -------------------------------
1010
1011// ECMA 11.4.9
1012ValueImp *LogicalNotNode::evaluate(ExecState *exec)
1013{
1014 ValueImp *v = expr->evaluate(exec);
1015 KJS_CHECKEXCEPTIONVALUE
1016 return jsBoolean(!v->toBoolean(exec));
1017}
1018
1019// ------------------------------ MultNode -------------------------------------
1020
1021// ECMA 11.5
1022ValueImp *MultNode::evaluate(ExecState *exec)
1023{
1024 ValueImp *v1 = term1->evaluate(exec);
1025 KJS_CHECKEXCEPTIONVALUE
1026
1027 ValueImp *v2 = term2->evaluate(exec);
1028 KJS_CHECKEXCEPTIONVALUE
1029
1030 return mult(exec, v1, v2, oper);
1031}
1032
1033// ------------------------------ AddNode --------------------------------------
1034
1035// ECMA 11.6
1036ValueImp *AddNode::evaluate(ExecState *exec)
1037{
1038 ValueImp *v1 = term1->evaluate(exec);
1039 KJS_CHECKEXCEPTIONVALUE
1040
1041 ValueImp *v2 = term2->evaluate(exec);
1042 KJS_CHECKEXCEPTIONVALUE
1043
1044 return add(exec, v1, v2, oper);
1045}
1046
1047// ------------------------------ ShiftNode ------------------------------------
1048
1049// ECMA 11.7
1050ValueImp *ShiftNode::evaluate(ExecState *exec)
1051{
1052 ValueImp *v1 = term1->evaluate(exec);
1053 KJS_CHECKEXCEPTIONVALUE
1054 ValueImp *v2 = term2->evaluate(exec);
1055 KJS_CHECKEXCEPTIONVALUE
1056 unsigned int i2 = v2->toUInt32(exec);
1057 i2 &= 0x1f;
1058
1059 switch (oper) {
1060 case OpLShift:
1061 return jsNumber(v1->toInt32(exec) << i2);
1062 case OpRShift:
1063 return jsNumber(v1->toInt32(exec) >> i2);
1064 case OpURShift:
1065 return jsNumber(v1->toUInt32(exec) >> i2);
1066 default:
1067 assert(!"ShiftNode: unhandled switch case");
1068 return Undefined();
1069 }
1070}
1071
1072// ------------------------------ RelationalNode -------------------------------
1073
1074// ECMA 11.8
1075ValueImp *RelationalNode::evaluate(ExecState *exec)
1076{
1077 ValueImp *v1 = expr1->evaluate(exec);
1078 KJS_CHECKEXCEPTIONVALUE
1079 ValueImp *v2 = expr2->evaluate(exec);
1080 KJS_CHECKEXCEPTIONVALUE
1081
1082 bool b;
1083 if (oper == OpLess || oper == OpGreaterEq) {
1084 int r = relation(exec, v1, v2);
1085 if (r < 0)
1086 b = false;
1087 else
1088 b = (oper == OpLess) ? (r == 1) : (r == 0);
1089 } else if (oper == OpGreater || oper == OpLessEq) {
1090 int r = relation(exec, v2, v1);
1091 if (r < 0)
1092 b = false;
1093 else
1094 b = (oper == OpGreater) ? (r == 1) : (r == 0);
1095 } else if (oper == OpIn) {
1096 // Is all of this OK for host objects?
1097 if (!v2->isObject())
1098 return throwError(exec, TypeError,
1099 "Value %s (result of expression %s) is not an object. Cannot be used with IN expression.", v2, expr2.get());
1100 ObjectImp *o2(static_cast<ObjectImp*>(v2));
1101 b = o2->hasProperty(exec, Identifier(v1->toString(exec)));
1102 } else {
1103 if (!v2->isObject())
1104 return throwError(exec, TypeError,
1105 "Value %s (result of expression %s) is not an object. Cannot be used with instanceof operator.", v2, expr2.get());
1106
1107 ObjectImp *o2(static_cast<ObjectImp*>(v2));
1108 if (!o2->implementsHasInstance()) {
1109 // According to the spec, only some types of objects "implement" the [[HasInstance]] property.
1110 // But we are supposed to throw an exception where the object does not "have" the [[HasInstance]]
1111 // property. It seems that all object have the property, but not all implement it, so in this
1112 // case we return false (consistent with mozilla)
1113 return jsBoolean(false);
1114 // return throwError(exec, TypeError,
1115 // "Object does not implement the [[HasInstance]] method." );
1116 }
1117 return jsBoolean(o2->hasInstance(exec, v1));
1118 }
1119
1120 return jsBoolean(b);
1121}
1122
1123// ------------------------------ EqualNode ------------------------------------
1124
1125// ECMA 11.9
1126ValueImp *EqualNode::evaluate(ExecState *exec)
1127{
1128 ValueImp *v1 = expr1->evaluate(exec);
1129 KJS_CHECKEXCEPTIONVALUE
1130 ValueImp *v2 = expr2->evaluate(exec);
1131 KJS_CHECKEXCEPTIONVALUE
1132
1133 bool result;
1134 if (oper == OpEqEq || oper == OpNotEq) {
1135 // == and !=
1136 bool eq = equal(exec,v1, v2);
1137 result = oper == OpEqEq ? eq : !eq;
1138 } else {
1139 // === and !==
1140 bool eq = strictEqual(exec,v1, v2);
1141 result = oper == OpStrEq ? eq : !eq;
1142 }
1143 return jsBoolean(result);
1144}
1145
1146// ------------------------------ BitOperNode ----------------------------------
1147
1148// ECMA 11.10
1149ValueImp *BitOperNode::evaluate(ExecState *exec)
1150{
1151 ValueImp *v1 = expr1->evaluate(exec);
1152 KJS_CHECKEXCEPTIONVALUE
1153 ValueImp *v2 = expr2->evaluate(exec);
1154 KJS_CHECKEXCEPTIONVALUE
1155 int i1 = v1->toInt32(exec);
1156 int i2 = v2->toInt32(exec);
1157 int result;
1158 if (oper == OpBitAnd)
1159 result = i1 & i2;
1160 else if (oper == OpBitXOr)
1161 result = i1 ^ i2;
1162 else
1163 result = i1 | i2;
1164
1165 return jsNumber(result);
1166}
1167
1168// ------------------------------ BinaryLogicalNode ----------------------------
1169
1170// ECMA 11.11
1171ValueImp *BinaryLogicalNode::evaluate(ExecState *exec)
1172{
1173 ValueImp *v1 = expr1->evaluate(exec);
1174 KJS_CHECKEXCEPTIONVALUE
1175 bool b1 = v1->toBoolean(exec);
1176 if ((!b1 && oper == OpAnd) || (b1 && oper == OpOr))
1177 return v1;
1178
1179 ValueImp *v2 = expr2->evaluate(exec);
1180 KJS_CHECKEXCEPTIONVALUE
1181
1182 return v2;
1183}
1184
1185// ------------------------------ ConditionalNode ------------------------------
1186
1187// ECMA 11.12
1188ValueImp *ConditionalNode::evaluate(ExecState *exec)
1189{
1190 ValueImp *v = logical->evaluate(exec);
1191 KJS_CHECKEXCEPTIONVALUE
1192 bool b = v->toBoolean(exec);
1193
1194 if (b)
1195 v = expr1->evaluate(exec);
1196 else
1197 v = expr2->evaluate(exec);
1198 KJS_CHECKEXCEPTIONVALUE
1199
1200 return v;
1201}
1202
1203// ECMA 11.13
1204
1205#if __GNUC__
1206// gcc refuses to inline this without the always_inline, but inlining it does help
1207static inline ValueImp *valueForReadModifyAssignment(ExecState * exec, ValueImp *v1, ValueImp *v2, Operator oper) __attribute__((always_inline));
1208#endif
1209
1210static inline ValueImp *valueForReadModifyAssignment(ExecState * exec, ValueImp *v1, ValueImp *v2, Operator oper)
1211{
1212 ValueImp *v;
1213 int i1;
1214 int i2;
1215 unsigned int ui;
1216 switch (oper) {
1217 case OpMultEq:
1218 v = mult(exec, v1, v2, '*');
1219 break;
1220 case OpDivEq:
1221 v = mult(exec, v1, v2, '/');
1222 break;
1223 case OpPlusEq:
1224 v = add(exec, v1, v2, '+');
1225 break;
1226 case OpMinusEq:
1227 v = add(exec, v1, v2, '-');
1228 break;
1229 case OpLShift:
1230 i1 = v1->toInt32(exec);
1231 i2 = v2->toInt32(exec);
1232 v = jsNumber(i1 << i2);
1233 break;
1234 case OpRShift:
1235 i1 = v1->toInt32(exec);
1236 i2 = v2->toInt32(exec);
1237 v = jsNumber(i1 >> i2);
1238 break;
1239 case OpURShift:
1240 ui = v1->toUInt32(exec);
1241 i2 = v2->toInt32(exec);
1242 v = jsNumber(ui >> i2);
1243 break;
1244 case OpAndEq:
1245 i1 = v1->toInt32(exec);
1246 i2 = v2->toInt32(exec);
1247 v = jsNumber(i1 & i2);
1248 break;
1249 case OpXOrEq:
1250 i1 = v1->toInt32(exec);
1251 i2 = v2->toInt32(exec);
1252 v = jsNumber(i1 ^ i2);
1253 break;
1254 case OpOrEq:
1255 i1 = v1->toInt32(exec);
1256 i2 = v2->toInt32(exec);
1257 v = jsNumber(i1 | i2);
1258 break;
1259 case OpModEq: {
1260 bool d1KnownToBeInteger;
1261 double d1 = v1->toNumber(exec, d1KnownToBeInteger);
1262 bool d2KnownToBeInteger;
1263 double d2 = v2->toNumber(exec, d2KnownToBeInteger);
1264 v = jsNumber(fmod(d1, d2), d1KnownToBeInteger && d2KnownToBeInteger && d2 != 0);
1265 }
1266 break;
1267 default:
1268 assert(0);
1269 v = Undefined();
1270 }
1271
1272 return v;
1273}
1274
1275// ------------------------------ AssignResolveNode -----------------------------------
1276
1277ValueImp *AssignResolveNode::evaluate(ExecState *exec)
1278{
1279 const ScopeChain& chain = exec->context().imp()->scopeChain();
1280 ScopeChainIterator iter = chain.begin();
1281 ScopeChainIterator end = chain.end();
1282
1283 // we must always have something in the scope chain
1284 assert(iter != end);
1285
1286 PropertySlot slot;
1287 ObjectImp *base;
1288 do {
1289 base = *iter;
1290 if (base->getPropertySlot(exec, m_ident, slot))
1291 goto found;
1292
1293 ++iter;
1294 } while (iter != end);
1295
1296 if (m_oper != OpEqual)
1297 return throwUndefinedVariableError(exec, m_ident);
1298
1299 found:
1300 ValueImp *v;
1301
1302 if (m_oper == OpEqual) {
1303 v = m_right->evaluate(exec);
1304 } else {
1305 ValueImp *v1 = slot.getValue(exec, m_ident);
1306 KJS_CHECKEXCEPTIONVALUE
1307 ValueImp *v2 = m_right->evaluate(exec);
1308 v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
1309 }
1310
1311 KJS_CHECKEXCEPTIONVALUE
1312
1313 base->put(exec, m_ident, v);
1314 return v;
1315}
1316
1317// ------------------------------ AssignDotNode -----------------------------------
1318
1319ValueImp *AssignDotNode::evaluate(ExecState *exec)
1320{
1321 ValueImp *baseValue = m_base->evaluate(exec);
1322 KJS_CHECKEXCEPTIONVALUE
1323 ObjectImp *base = baseValue->toObject(exec);
1324
1325 ValueImp *v;
1326
1327 if (m_oper == OpEqual) {
1328 v = m_right->evaluate(exec);
1329 } else {
1330 PropertySlot slot;
1331 ValueImp *v1 = base->getPropertySlot(exec, m_ident, slot) ? slot.getValue(exec, m_ident) : Undefined();
1332 KJS_CHECKEXCEPTIONVALUE
1333 ValueImp *v2 = m_right->evaluate(exec);
1334 v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
1335 }
1336
1337 KJS_CHECKEXCEPTIONVALUE
1338
1339 base->put(exec, m_ident, v);
1340 return v;
1341}
1342
1343// ------------------------------ AssignBracketNode -----------------------------------
1344
1345ValueImp *AssignBracketNode::evaluate(ExecState *exec)
1346{
1347 ValueImp *baseValue = m_base->evaluate(exec);
1348 KJS_CHECKEXCEPTIONVALUE
1349 ValueImp *subscript = m_subscript->evaluate(exec);
1350 KJS_CHECKEXCEPTIONVALUE
1351
1352 ObjectImp *base = baseValue->toObject(exec);
1353
1354 uint32_t propertyIndex;
1355 if (subscript->getUInt32(propertyIndex)) {
1356 ValueImp *v;
1357 if (m_oper == OpEqual) {
1358 v = m_right->evaluate(exec);
1359 } else {
1360 PropertySlot slot;
1361 ValueImp *v1 = base->getPropertySlot(exec, propertyIndex, slot) ? slot.getValue(exec, propertyIndex) : Undefined();
1362 KJS_CHECKEXCEPTIONVALUE
1363 ValueImp *v2 = m_right->evaluate(exec);
1364 v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
1365 }
1366
1367 KJS_CHECKEXCEPTIONVALUE
1368
1369 base->put(exec, propertyIndex, v);
1370 return v;
1371 }
1372
1373 Identifier propertyName(subscript->toString(exec));
1374 ValueImp *v;
1375
1376 if (m_oper == OpEqual) {
1377 v = m_right->evaluate(exec);
1378 } else {
1379 PropertySlot slot;
1380 ValueImp *v1 = base->getPropertySlot(exec, propertyName, slot) ? slot.getValue(exec, propertyName) : Undefined();
1381 KJS_CHECKEXCEPTIONVALUE
1382 ValueImp *v2 = m_right->evaluate(exec);
1383 v = valueForReadModifyAssignment(exec, v1, v2, m_oper);
1384 }
1385
1386 KJS_CHECKEXCEPTIONVALUE
1387
1388 base->put(exec, propertyName, v);
1389 return v;
1390}
1391
1392// ------------------------------ CommaNode ------------------------------------
1393
1394// ECMA 11.14
1395ValueImp *CommaNode::evaluate(ExecState *exec)
1396{
1397 expr1->evaluate(exec);
1398 KJS_CHECKEXCEPTIONVALUE
1399 ValueImp *v = expr2->evaluate(exec);
1400 KJS_CHECKEXCEPTIONVALUE
1401
1402 return v;
1403}
1404
1405// ------------------------------ StatListNode ---------------------------------
1406
1407StatListNode::StatListNode(StatementNode *s)
1408 : statement(s), list(this)
1409{
1410 setLoc(s->firstLine(), s->lastLine(), s->sourceId());
1411}
1412
1413StatListNode::StatListNode(StatListNode *l, StatementNode *s)
1414 : statement(s), list(l->list)
1415{
1416 l->list = this;
1417 setLoc(l->firstLine(), s->lastLine(), l->sourceId());
1418}
1419
1420// ECMA 12.1
1421Completion StatListNode::execute(ExecState *exec)
1422{
1423 Completion c = statement->execute(exec);
1424 KJS_ABORTPOINT
1425 if (c.complType() != Normal)
1426 return c;
1427
1428 ValueImp *v = c.value();
1429
1430 for (StatListNode *n = list.get(); n; n = n->list.get()) {
1431 Completion c2 = n->statement->execute(exec);
1432 KJS_ABORTPOINT
1433 if (c2.complType() != Normal)
1434 return c2;
1435
1436 if (c2.isValueCompletion())
1437 v = c2.value();
1438 c = c2;
1439 }
1440
1441 return Completion(c.complType(), v, c.target());
1442}
1443
1444void StatListNode::processVarDecls(ExecState *exec)
1445{
1446 for (StatListNode *n = this; n; n = n->list.get())
1447 n->statement->processVarDecls(exec);
1448}
1449
1450// ------------------------------ AssignExprNode -------------------------------
1451
1452// ECMA 12.2
1453ValueImp *AssignExprNode::evaluate(ExecState *exec)
1454{
1455 return expr->evaluate(exec);
1456}
1457
1458// ------------------------------ VarDeclNode ----------------------------------
1459
1460
1461VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in, Type t)
1462 : varType(t), ident(id), init(in)
1463{
1464}
1465
1466// ECMA 12.2
1467ValueImp *VarDeclNode::evaluate(ExecState *exec)
1468{
1469 ObjectImp *variable = exec->context().imp()->variableObject();
1470
1471 ValueImp *val;
1472 if (init) {
1473 val = init->evaluate(exec);
1474 KJS_CHECKEXCEPTIONVALUE
1475 } else {
1476 // already declared? - check with getDirect so you can override
1477 // built-in properties of the global object with var declarations.
1478 if (variable->getDirect(ident))
1479 return 0;
1480 val = Undefined();
1481 }
1482
1483#ifdef KJS_VERBOSE
1484 printInfo(exec,(UString("new variable ")+ident.ustring()).cstring().c_str(),val);
1485#endif
1486 // We use Internal to bypass all checks in derived objects, e.g. so that
1487 // "var location" creates a dynamic property instead of activating window.location.
1488 int flags = Internal;
1489 if (exec->context().imp()->codeType() != EvalCode)
1490 flags |= DontDelete;
1491 if (varType == VarDeclNode::Constant)
1492 flags |= ReadOnly;
1493 variable->put(exec, ident, val, flags);
1494
1495 return jsString(ident.ustring());
1496}
1497
1498void VarDeclNode::processVarDecls(ExecState *exec)
1499{
1500 ObjectImp *variable = exec->context().imp()->variableObject();
1501
1502 // If a variable by this name already exists, don't clobber it -
1503 // it might be a function parameter
1504 if (!variable->hasProperty(exec, ident)) {
1505 int flags = Internal;
1506 if (exec->context().imp()->codeType() != EvalCode)
1507 flags |= DontDelete;
1508 if (varType == VarDeclNode::Constant)
1509 flags |= ReadOnly;
1510 variable->put(exec, ident, Undefined(), flags);
1511 }
1512}
1513
1514// ------------------------------ VarDeclListNode ------------------------------
1515
1516// ECMA 12.2
1517ValueImp *VarDeclListNode::evaluate(ExecState *exec)
1518{
1519 for (VarDeclListNode *n = this; n; n = n->list.get()) {
1520 n->var->evaluate(exec);
1521 KJS_CHECKEXCEPTIONVALUE
1522 }
1523 return Undefined();
1524}
1525
1526void VarDeclListNode::processVarDecls(ExecState *exec)
1527{
1528 for (VarDeclListNode *n = this; n; n = n->list.get())
1529 n->var->processVarDecls(exec);
1530}
1531
1532// ------------------------------ VarStatementNode -----------------------------
1533
1534// ECMA 12.2
1535Completion VarStatementNode::execute(ExecState *exec)
1536{
1537 KJS_BREAKPOINT;
1538
1539 (void) list->evaluate(exec);
1540 KJS_CHECKEXCEPTION
1541
1542 return Completion(Normal);
1543}
1544
1545void VarStatementNode::processVarDecls(ExecState *exec)
1546{
1547 list->processVarDecls(exec);
1548}
1549
1550// ------------------------------ BlockNode ------------------------------------
1551
1552BlockNode::BlockNode(SourceElementsNode *s)
1553{
1554 if (s) {
1555 source = s->elements;
1556 s->elements = 0;
1557 setLoc(s->firstLine(), s->lastLine(), s->sourceId());
1558 } else {
1559 source = 0;
1560 }
1561}
1562
1563// ECMA 12.1
1564Completion BlockNode::execute(ExecState *exec)
1565{
1566 if (!source)
1567 return Completion(Normal);
1568
1569 source->processFuncDecl(exec);
1570
1571 return source->execute(exec);
1572}
1573
1574void BlockNode::processVarDecls(ExecState *exec)
1575{
1576 if (source)
1577 source->processVarDecls(exec);
1578}
1579
1580// ------------------------------ EmptyStatementNode ---------------------------
1581
1582// ECMA 12.3
1583Completion EmptyStatementNode::execute(ExecState *)
1584{
1585 return Completion(Normal);
1586}
1587
1588// ------------------------------ ExprStatementNode ----------------------------
1589
1590// ECMA 12.4
1591Completion ExprStatementNode::execute(ExecState *exec)
1592{
1593 KJS_BREAKPOINT;
1594
1595 ValueImp *v = expr->evaluate(exec);
1596 KJS_CHECKEXCEPTION
1597
1598 return Completion(Normal, v);
1599}
1600
1601// ------------------------------ IfNode ---------------------------------------
1602
1603// ECMA 12.5
1604Completion IfNode::execute(ExecState *exec)
1605{
1606 KJS_BREAKPOINT;
1607
1608 ValueImp *v = expr->evaluate(exec);
1609 KJS_CHECKEXCEPTION
1610 bool b = v->toBoolean(exec);
1611
1612 // if ... then
1613 if (b)
1614 return statement1->execute(exec);
1615
1616 // no else
1617 if (!statement2)
1618 return Completion(Normal);
1619
1620 // else
1621 return statement2->execute(exec);
1622}
1623
1624void IfNode::processVarDecls(ExecState *exec)
1625{
1626 statement1->processVarDecls(exec);
1627
1628 if (statement2)
1629 statement2->processVarDecls(exec);
1630}
1631
1632// ------------------------------ DoWhileNode ----------------------------------
1633
1634// ECMA 12.6.1
1635Completion DoWhileNode::execute(ExecState *exec)
1636{
1637 KJS_BREAKPOINT;
1638
1639 ValueImp *bv;
1640 Completion c;
1641
1642 do {
1643 // bail out on error
1644 KJS_CHECKEXCEPTION
1645
1646 exec->context().imp()->seenLabels()->pushIteration();
1647 c = statement->execute(exec);
1648 exec->context().imp()->seenLabels()->popIteration();
1649 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1650 if ((c.complType() == Break) && ls.contains(c.target()))
1651 return Completion(Normal, 0);
1652 if (c.complType() != Normal)
1653 return c;
1654 }
1655 bv = expr->evaluate(exec);
1656 KJS_CHECKEXCEPTION
1657 } while (bv->toBoolean(exec));
1658
1659 return Completion(Normal, 0);
1660}
1661
1662void DoWhileNode::processVarDecls(ExecState *exec)
1663{
1664 statement->processVarDecls(exec);
1665}
1666
1667// ------------------------------ WhileNode ------------------------------------
1668
1669// ECMA 12.6.2
1670Completion WhileNode::execute(ExecState *exec)
1671{
1672 KJS_BREAKPOINT;
1673
1674 ValueImp *bv;
1675 Completion c;
1676 bool b(false);
1677 ValueImp *value = 0;
1678
1679 while (1) {
1680 bv = expr->evaluate(exec);
1681 KJS_CHECKEXCEPTION
1682 b = bv->toBoolean(exec);
1683
1684 // bail out on error
1685 KJS_CHECKEXCEPTION
1686
1687 if (!b)
1688 return Completion(Normal, value);
1689
1690 exec->context().imp()->seenLabels()->pushIteration();
1691 c = statement->execute(exec);
1692 exec->context().imp()->seenLabels()->popIteration();
1693 if (c.isValueCompletion())
1694 value = c.value();
1695
1696 if ((c.complType() == Continue) && ls.contains(c.target()))
1697 continue;
1698 if ((c.complType() == Break) && ls.contains(c.target()))
1699 return Completion(Normal, value);
1700 if (c.complType() != Normal)
1701 return c;
1702 }
1703
1704 return Completion(); // work around gcc 4.0 bug
1705}
1706
1707void WhileNode::processVarDecls(ExecState *exec)
1708{
1709 statement->processVarDecls(exec);
1710}
1711
1712// ------------------------------ ForNode --------------------------------------
1713
1714// ECMA 12.6.3
1715Completion ForNode::execute(ExecState *exec)
1716{
1717 ValueImp *v, *cval = 0;
1718
1719 if (expr1) {
1720 v = expr1->evaluate(exec);
1721 KJS_CHECKEXCEPTION
1722 }
1723 while (1) {
1724 if (expr2) {
1725 v = expr2->evaluate(exec);
1726 KJS_CHECKEXCEPTION
1727 if (!v->toBoolean(exec))
1728 return Completion(Normal, cval);
1729 }
1730 // bail out on error
1731 KJS_CHECKEXCEPTION
1732
1733 exec->context().imp()->seenLabels()->pushIteration();
1734 Completion c = statement->execute(exec);
1735 exec->context().imp()->seenLabels()->popIteration();
1736 if (c.isValueCompletion())
1737 cval = c.value();
1738 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1739 if ((c.complType() == Break) && ls.contains(c.target()))
1740 return Completion(Normal, cval);
1741 if (c.complType() != Normal)
1742 return c;
1743 }
1744 if (expr3) {
1745 v = expr3->evaluate(exec);
1746 KJS_CHECKEXCEPTION
1747 }
1748 }
1749
1750 return Completion(); // work around gcc 4.0 bug
1751}
1752
1753void ForNode::processVarDecls(ExecState *exec)
1754{
1755 if (expr1)
1756 expr1->processVarDecls(exec);
1757
1758 statement->processVarDecls(exec);
1759}
1760
1761// ------------------------------ ForInNode ------------------------------------
1762
1763ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
1764 : init(0L), lexpr(l), expr(e), varDecl(0L), statement(s)
1765{
1766}
1767
1768ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
1769 : ident(i), init(in), expr(e), statement(s)
1770{
1771 // for( var foo = bar in baz )
1772 varDecl = new VarDeclNode(ident, init.get(), VarDeclNode::Variable);
1773 lexpr = new ResolveNode(ident);
1774}
1775
1776// ECMA 12.6.4
1777Completion ForInNode::execute(ExecState *exec)
1778{
1779 ValueImp *e;
1780 ValueImp *retval = 0;
1781 ObjectImp *v;
1782 Completion c;
1783 ReferenceList propList;
1784
1785 if (varDecl) {
1786 varDecl->evaluate(exec);
1787 KJS_CHECKEXCEPTION
1788 }
1789
1790 e = expr->evaluate(exec);
1791
1792 // for Null and Undefined, we want to make sure not to go through
1793 // the loop at all, because their object wrappers will have a
1794 // property list but will throw an exception if you attempt to
1795 // access any property.
1796 if (e->isUndefinedOrNull()) {
1797 return Completion(Normal, 0);
1798 }
1799
1800 KJS_CHECKEXCEPTION
1801 v = e->toObject(exec);
1802 propList = v->propList(exec);
1803
1804 ReferenceListIterator propIt = propList.begin();
1805
1806 while (propIt != propList.end()) {
1807 Identifier name = propIt->getPropertyName(exec);
1808 if (!v->hasProperty(exec, name)) {
1809 propIt++;
1810 continue;
1811 }
1812
1813 ValueImp *str = jsString(name.ustring());
1814
1815 if (lexpr->isResolveNode()) {
1816 const Identifier &ident = static_cast<ResolveNode *>(lexpr.get())->identifier();
1817
1818 const ScopeChain& chain = exec->context().imp()->scopeChain();
1819 ScopeChainIterator iter = chain.begin();
1820 ScopeChainIterator end = chain.end();
1821
1822 // we must always have something in the scope chain
1823 assert(iter != end);
1824
1825 PropertySlot slot;
1826 ObjectImp *o;
1827 do {
1828 o = *iter;
1829 if (o->getPropertySlot(exec, ident, slot))
1830 o->put(exec, ident, str);
1831
1832 ++iter;
1833 } while (iter != end);
1834
1835 if (iter == end)
1836 o->put(exec, ident, str);
1837 } else if (lexpr->isDotAccessorNode()) {
1838 const Identifier& ident = static_cast<DotAccessorNode *>(lexpr.get())->identifier();
1839 ValueImp *v = static_cast<DotAccessorNode *>(lexpr.get())->base()->evaluate(exec);
1840 KJS_CHECKEXCEPTION
1841 ObjectImp *o = v->toObject(exec);
1842
1843 o->put(exec, ident, str);
1844 } else {
1845 assert(lexpr->isBracketAccessorNode());
1846 ValueImp *v = static_cast<BracketAccessorNode *>(lexpr.get())->base()->evaluate(exec);
1847 KJS_CHECKEXCEPTION
1848 ValueImp *v2 = static_cast<BracketAccessorNode *>(lexpr.get())->subscript()->evaluate(exec);
1849 KJS_CHECKEXCEPTION
1850 ObjectImp *o = v->toObject(exec);
1851
1852 uint32_t i;
1853 if (v2->getUInt32(i))
1854 o->put(exec, i, str);
1855 o->put(exec, Identifier(v2->toString(exec)), str);
1856 }
1857
1858 KJS_CHECKEXCEPTION
1859
1860 exec->context().imp()->seenLabels()->pushIteration();
1861 c = statement->execute(exec);
1862 exec->context().imp()->seenLabels()->popIteration();
1863 if (c.isValueCompletion())
1864 retval = c.value();
1865
1866 if (!((c.complType() == Continue) && ls.contains(c.target()))) {
1867 if ((c.complType() == Break) && ls.contains(c.target()))
1868 break;
1869 if (c.complType() != Normal) {
1870 return c;
1871 }
1872 }
1873
1874 propIt++;
1875 }
1876
1877 // bail out on error
1878 KJS_CHECKEXCEPTION
1879
1880 return Completion(Normal, retval);
1881}
1882
1883void ForInNode::processVarDecls(ExecState *exec)
1884{
1885 statement->processVarDecls(exec);
1886}
1887
1888// ------------------------------ ContinueNode ---------------------------------
1889
1890// ECMA 12.7
1891Completion ContinueNode::execute(ExecState *exec)
1892{
1893 KJS_BREAKPOINT;
1894
1895 if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration())
1896 return createErrorCompletion(exec, SyntaxError, "Invalid continue statement.");
1897 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
1898 return createErrorCompletion(exec, SyntaxError, "Label %s not found.", ident);
1899 else
1900 return Completion(Continue, 0, ident);
1901}
1902
1903// ------------------------------ BreakNode ------------------------------------
1904
1905// ECMA 12.8
1906Completion BreakNode::execute(ExecState *exec)
1907{
1908 KJS_BREAKPOINT;
1909
1910 if (ident.isEmpty() && !exec->context().imp()->seenLabels()->inIteration() &&
1911 !exec->context().imp()->seenLabels()->inSwitch())
1912 return createErrorCompletion(exec, SyntaxError, "Invalid break statement.");
1913 else if (!ident.isEmpty() && !exec->context().imp()->seenLabels()->contains(ident))
1914 return createErrorCompletion(exec, SyntaxError, "Label %s not found.");
1915 else
1916 return Completion(Break, 0, ident);
1917}
1918
1919// ------------------------------ ReturnNode -----------------------------------
1920
1921// ECMA 12.9
1922Completion ReturnNode::execute(ExecState *exec)
1923{
1924 KJS_BREAKPOINT;
1925
1926 CodeType codeType = exec->context().imp()->codeType();
1927 if (codeType != FunctionCode && codeType != AnonymousCode ) {
1928 return createErrorCompletion(exec, SyntaxError, "Invalid return statement.");
1929 }
1930
1931 if (!value)
1932 return Completion(ReturnValue, Undefined());
1933
1934 ValueImp *v = value->evaluate(exec);
1935 KJS_CHECKEXCEPTION
1936
1937 return Completion(ReturnValue, v);
1938}
1939
1940// ------------------------------ WithNode -------------------------------------
1941
1942// ECMA 12.10
1943Completion WithNode::execute(ExecState *exec)
1944{
1945 KJS_BREAKPOINT;
1946
1947 ValueImp *v = expr->evaluate(exec);
1948 KJS_CHECKEXCEPTION
1949 ObjectImp *o = v->toObject(exec);
1950 KJS_CHECKEXCEPTION
1951 exec->context().imp()->pushScope(o);
1952 Completion res = statement->execute(exec);
1953 exec->context().imp()->popScope();
1954
1955 return res;
1956}
1957
1958void WithNode::processVarDecls(ExecState *exec)
1959{
1960 statement->processVarDecls(exec);
1961}
1962
1963// ------------------------------ CaseClauseNode -------------------------------
1964
1965// ECMA 12.11
1966ValueImp *CaseClauseNode::evaluate(ExecState *exec)
1967{
1968 ValueImp *v = expr->evaluate(exec);
1969 KJS_CHECKEXCEPTIONVALUE
1970
1971 return v;
1972}
1973
1974// ECMA 12.11
1975Completion CaseClauseNode::evalStatements(ExecState *exec)
1976{
1977 if (list)
1978 return list->execute(exec);
1979 else
1980 return Completion(Normal, Undefined());
1981}
1982
1983void CaseClauseNode::processVarDecls(ExecState *exec)
1984{
1985 if (list)
1986 list->processVarDecls(exec);
1987}
1988
1989// ------------------------------ ClauseListNode -------------------------------
1990
1991ValueImp *ClauseListNode::evaluate(ExecState *)
1992{
1993 // should never be called
1994 assert(false);
1995 return 0;
1996}
1997
1998// ECMA 12.11
1999void ClauseListNode::processVarDecls(ExecState *exec)
2000{
2001 for (ClauseListNode *n = this; n; n = n->nx.get())
2002 if (n->cl)
2003 n->cl->processVarDecls(exec);
2004}
2005
2006// ------------------------------ CaseBlockNode --------------------------------
2007
2008CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
2009 ClauseListNode *l2)
2010{
2011 if (l1) {
2012 list1 = l1->nx;
2013 l1->nx = 0;
2014 } else {
2015 list1 = 0;
2016 }
2017
2018 def = d;
2019
2020 if (l2) {
2021 list2 = l2->nx;
2022 l2->nx = 0;
2023 } else {
2024 list2 = 0;
2025 }
2026}
2027
2028ValueImp *CaseBlockNode::evaluate(ExecState *)
2029{
2030 // should never be called
2031 assert(false);
2032 return 0;
2033}
2034
2035// ECMA 12.11
2036Completion CaseBlockNode::evalBlock(ExecState *exec, ValueImp *input)
2037{
2038 ValueImp *v;
2039 Completion res;
2040 ClauseListNode *a = list1.get();
2041 ClauseListNode *b = list2.get();
2042 CaseClauseNode *clause;
2043
2044 while (a) {
2045 clause = a->clause();
2046 a = a->next();
2047 v = clause->evaluate(exec);
2048 KJS_CHECKEXCEPTION
2049 if (strictEqual(exec, input, v)) {
2050 res = clause->evalStatements(exec);
2051 if (res.complType() != Normal)
2052 return res;
2053 while (a) {
2054 res = a->clause()->evalStatements(exec);
2055 if (res.complType() != Normal)
2056 return res;
2057 a = a->next();
2058 }
2059 break;
2060 }
2061 }
2062
2063 while (b) {
2064 clause = b->clause();
2065 b = b->next();
2066 v = clause->evaluate(exec);
2067 KJS_CHECKEXCEPTION
2068 if (strictEqual(exec, input, v)) {
2069 res = clause->evalStatements(exec);
2070 if (res.complType() != Normal)
2071 return res;
2072 goto step18;
2073 }
2074 }
2075
2076 // default clause
2077 if (def) {
2078 res = def->evalStatements(exec);
2079 if (res.complType() != Normal)
2080 return res;
2081 }
2082 b = list2.get();
2083 step18:
2084 while (b) {
2085 clause = b->clause();
2086 res = clause->evalStatements(exec);
2087 if (res.complType() != Normal)
2088 return res;
2089 b = b->next();
2090 }
2091
2092 // bail out on error
2093 KJS_CHECKEXCEPTION
2094
2095 return Completion(Normal);
2096}
2097
2098void CaseBlockNode::processVarDecls(ExecState *exec)
2099{
2100 if (list1)
2101 list1->processVarDecls(exec);
2102 if (def)
2103 def->processVarDecls(exec);
2104 if (list2)
2105 list2->processVarDecls(exec);
2106}
2107
2108// ------------------------------ SwitchNode -----------------------------------
2109
2110// ECMA 12.11
2111Completion SwitchNode::execute(ExecState *exec)
2112{
2113 KJS_BREAKPOINT;
2114
2115 ValueImp *v = expr->evaluate(exec);
2116 KJS_CHECKEXCEPTION
2117
2118 exec->context().imp()->seenLabels()->pushSwitch();
2119 Completion res = block->evalBlock(exec,v);
2120 exec->context().imp()->seenLabels()->popSwitch();
2121
2122 if ((res.complType() == Break) && ls.contains(res.target()))
2123 return Completion(Normal, res.value());
2124 return res;
2125}
2126
2127void SwitchNode::processVarDecls(ExecState *exec)
2128{
2129 block->processVarDecls(exec);
2130}
2131
2132// ------------------------------ LabelNode ------------------------------------
2133
2134// ECMA 12.12
2135Completion LabelNode::execute(ExecState *exec)
2136{
2137 if (!exec->context().imp()->seenLabels()->push(label))
2138 return createErrorCompletion(exec, SyntaxError, "Duplicated label %s found.", label);
2139 Completion e = statement->execute(exec);
2140 exec->context().imp()->seenLabels()->pop();
2141
2142 if ((e.complType() == Break) && (e.target() == label))
2143 return Completion(Normal, e.value());
2144 return e;
2145}
2146
2147void LabelNode::processVarDecls(ExecState *exec)
2148{
2149 statement->processVarDecls(exec);
2150}
2151
2152// ------------------------------ ThrowNode ------------------------------------
2153
2154// ECMA 12.13
2155Completion ThrowNode::execute(ExecState *exec)
2156{
2157 KJS_BREAKPOINT;
2158
2159 ValueImp *v = expr->evaluate(exec);
2160 KJS_CHECKEXCEPTION
2161
2162 return Completion(Throw, v);
2163}
2164
2165// ------------------------------ TryNode --------------------------------------
2166
2167// ECMA 12.14
2168Completion TryNode::execute(ExecState *exec)
2169{
2170 KJS_BREAKPOINT;
2171
2172 Completion c = tryBlock->execute(exec);
2173
2174 if (catchBlock && c.complType() == Throw) {
2175 ObjectImp *obj = new ObjectImp;
2176 obj->put(exec, exceptionIdent, c.value(), DontDelete);
2177 exec->context().imp()->pushScope(obj);
2178 c = catchBlock->execute(exec);
2179 exec->context().imp()->popScope();
2180 }
2181
2182 if (finallyBlock) {
2183 Completion c2 = finallyBlock->execute(exec);
2184 if (c2.complType() != Normal)
2185 c = c2;
2186 }
2187
2188 return c;
2189}
2190
2191void TryNode::processVarDecls(ExecState *exec)
2192{
2193 tryBlock->processVarDecls(exec);
2194 if (catchBlock)
2195 catchBlock->processVarDecls(exec);
2196 if (finallyBlock)
2197 finallyBlock->processVarDecls(exec);
2198}
2199
2200// ------------------------------ ParameterNode --------------------------------
2201
2202// ECMA 13
2203ValueImp *ParameterNode::evaluate(ExecState *)
2204{
2205 return Undefined();
2206}
2207
2208// ------------------------------ FunctionBodyNode -----------------------------
2209
2210FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
2211 : BlockNode(s)
2212{
2213 setLoc(-1, -1, -1);
2214}
2215
2216void FunctionBodyNode::processFuncDecl(ExecState *exec)
2217{
2218 if (source)
2219 source->processFuncDecl(exec);
2220}
2221
2222// ------------------------------ FuncDeclNode ---------------------------------
2223
2224// ECMA 13
2225void FuncDeclNode::processFuncDecl(ExecState *exec)
2226{
2227 ContextImp *context = exec->context().imp();
2228
2229 // TODO: let this be an object with [[Class]] property "Function"
2230 FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
2231
2232 ObjectImp *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
2233 proto->put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2234 func->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2235
2236 int plen = 0;
2237 for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
2238 func->addParameter(p->ident());
2239
2240 func->put(exec, lengthPropertyName, Number(plen), ReadOnly|DontDelete|DontEnum);
2241
2242 // ECMA 10.2.2
2243 context->variableObject()->put(exec, ident, func, Internal | (context->codeType() == EvalCode ? 0 : DontDelete));
2244
2245 if (body) {
2246 // hack the scope so that the function gets put as a property of func, and it's scope
2247 // contains the func as well as our current scope
2248 ObjectImp *oldVar = context->variableObject();
2249 context->setVariableObject(func);
2250 context->pushScope(func);
2251 body->processFuncDecl(exec);
2252 context->popScope();
2253 context->setVariableObject(oldVar);
2254 }
2255}
2256
2257Completion FuncDeclNode::execute(ExecState *)
2258{
2259 return Completion(Normal);
2260}
2261
2262// ------------------------------ FuncExprNode ---------------------------------
2263
2264// ECMA 13
2265ValueImp *FuncExprNode::evaluate(ExecState *exec)
2266{
2267 ContextImp *context = exec->context().imp();
2268 bool named = !ident.isNull();
2269 ObjectImp *functionScopeObject = 0;
2270
2271 if (named) {
2272 // named FunctionExpressions can recursively call themselves,
2273 // but they won't register with the current scope chain and should
2274 // be contained as single property in an anonymous object.
2275 functionScopeObject = new ObjectImp;
2276 context->pushScope(functionScopeObject);
2277 }
2278
2279 FunctionImp *func = new DeclaredFunctionImp(exec, ident, body.get(), context->scopeChain());
2280 ObjectImp *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
2281 proto->put(exec, constructorPropertyName, func, ReadOnly|DontDelete|DontEnum);
2282 func->put(exec, prototypePropertyName, proto, Internal|DontDelete);
2283
2284 int plen = 0;
2285 for(ParameterNode *p = param.get(); p != 0L; p = p->nextParam(), plen++)
2286 func->addParameter(p->ident());
2287
2288 if (named) {
2289 functionScopeObject->put(exec, ident, func, Internal | ReadOnly | (context->codeType() == EvalCode ? 0 : DontDelete));
2290 context->popScope();
2291 }
2292
2293 return func;
2294}
2295
2296// ------------------------------ SourceElementsNode ---------------------------
2297
2298SourceElementsNode::SourceElementsNode(StatementNode *s1)
2299 : element(s1), elements(this)
2300{
2301 setLoc(s1->firstLine(), s1->lastLine(), s1->sourceId());
2302}
2303
2304SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
2305 : element(s2), elements(s1->elements)
2306{
2307 s1->elements = this;
2308 setLoc(s1->firstLine(), s2->lastLine(), s1->sourceId());
2309}
2310
2311// ECMA 14
2312Completion SourceElementsNode::execute(ExecState *exec)
2313{
2314 KJS_CHECKEXCEPTION
2315
2316 Completion c1 = element->execute(exec);
2317 KJS_CHECKEXCEPTION;
2318 if (c1.complType() != Normal)
2319 return c1;
2320
2321 for (SourceElementsNode *n = elements.get(); n; n = n->elements.get()) {
2322 Completion c2 = n->element->execute(exec);
2323 if (c2.complType() != Normal)
2324 return c2;
2325 // The spec says to return c2 here, but it seems that mozilla returns c1 if
2326 // c2 doesn't have a value
2327 if (c2.value())
2328 c1 = c2;
2329 }
2330
2331 return c1;
2332}
2333
2334// ECMA 14
2335void SourceElementsNode::processFuncDecl(ExecState *exec)
2336{
2337 for (SourceElementsNode *n = this; n; n = n->elements.get())
2338 n->element->processFuncDecl(exec);
2339}
2340
2341void SourceElementsNode::processVarDecls(ExecState *exec)
2342{
2343 for (SourceElementsNode *n = this; n; n = n->elements.get())
2344 n->element->processVarDecls(exec);
2345}
2346
2347ProgramNode::ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s)
2348{
2349}
Note: See TracBrowser for help on using the repository browser.