1 /*
2 * This file is part of the KDE libraries
3 * Copyright (C) 1999-2002 Harri Porten (porten@kde.org)
4 * Copyright (C) 2001 Peter Kelly (pmk@post.com)
5 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
6 * Copyright (C) 2007 Maksim Orlovich (maksim@kde.org)
7 *
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Library General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
12 *
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Library General Public License for more details.
17 *
18 * You should have received a copy of the GNU Library General Public License
19 * along with this library; see the file COPYING.LIB. If not, write to
20 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22 *
23 */
24
25 #include "nodes.h"
26 #include "scriptfunction.h"
27
28 #include <math.h>
29 #include <stdio.h>
30 #ifdef KJS_DEBUG_MEM
31 #include <typeinfo>
32 #endif
33
34 //#include <iostream>
35
36 #include "debugger.h"
37 #include "function_object.h"
38 #include "lexer.h"
39 #include "package.h"
40 #include "PropertyNameArray.h"
41 #include <wtf/AlwaysInline.h>
42 #include <wtf/Assertions.h>
43 #include <wtf/HashSet.h>
44 #include <wtf/HashCountedSet.h>
45 #include <wtf/MathExtras.h>
46
47 #include "bytecode/machine.h"
48
49 namespace KJS
50 {
51
52 // ------------------------------ Node -----------------------------------------
53
54 #ifndef NDEBUG
55 struct NodeCounter {
56 static unsigned count;
~NodeCounterKJS::NodeCounter57 ~NodeCounter()
58 {
59 if (count) {
60 fprintf(stderr, "LEAK: %d KJS::Node\n", count);
61 }
62 }
63 };
64 unsigned NodeCounter::count = 0;
65 static NodeCounter nodeCounter;
66 #endif
67
68 static HashSet<Node *> *newNodes;
69 static HashCountedSet<Node *> *nodeExtraRefCounts;
70
Node()71 Node::Node()
72 {
73 #ifndef NDEBUG
74 ++NodeCounter::count;
75 #endif
76 m_line = lexer().lineNo();
77 if (!newNodes) {
78 newNodes = new HashSet<Node *>;
79 }
80 newNodes->add(this);
81 }
82
~Node()83 Node::~Node()
84 {
85 #ifndef NDEBUG
86 --NodeCounter::count;
87 #endif
88 }
89
ref()90 void Node::ref()
91 {
92 // bumping from 0 to 1 is just removing from the new nodes set
93 if (newNodes) {
94 HashSet<Node *>::iterator it = newNodes->find(this);
95 if (it != newNodes->end()) {
96 newNodes->remove(it);
97 ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
98 return;
99 }
100 }
101
102 ASSERT(!newNodes || !newNodes->contains(this));
103
104 if (!nodeExtraRefCounts) {
105 nodeExtraRefCounts = new HashCountedSet<Node *>;
106 }
107 nodeExtraRefCounts->add(this);
108 }
109
deref()110 void Node::deref()
111 {
112 ASSERT(!newNodes || !newNodes->contains(this));
113
114 if (!nodeExtraRefCounts) {
115 delete this;
116 return;
117 }
118
119 HashCountedSet<Node *>::iterator it = nodeExtraRefCounts->find(this);
120 if (it == nodeExtraRefCounts->end()) {
121 delete this;
122 } else {
123 nodeExtraRefCounts->remove(it);
124 }
125 }
126
refcount()127 unsigned Node::refcount()
128 {
129 if (newNodes && newNodes->contains(this)) {
130 ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(this));
131 return 0;
132 }
133
134 ASSERT(!newNodes || !newNodes->contains(this));
135
136 if (!nodeExtraRefCounts) {
137 return 1;
138 }
139
140 return 1 + nodeExtraRefCounts->count(this);
141 }
142
clearNewNodes()143 void Node::clearNewNodes()
144 {
145 if (!newNodes) {
146 return;
147 }
148
149 #ifndef NDEBUG
150 HashSet<Node *>::iterator end = newNodes->end();
151 for (HashSet<Node *>::iterator it = newNodes->begin(); it != end; ++it) {
152 ASSERT(!nodeExtraRefCounts || !nodeExtraRefCounts->contains(*it));
153 }
154 #endif
155 deleteAllValues(*newNodes);
156 delete newNodes;
157 newNodes = nullptr;
158 }
159
substitute(UString & string,const UString & substring)160 static void substitute(UString &string, const UString &substring)
161 {
162 int position = string.find("%s");
163 assert(position != -1);
164 UString newString = string.substr(0, position);
165 newString.append(substring);
166 newString.append(string.substr(position + 2));
167 string = newString;
168 }
169
currentSourceId(ExecState * exec)170 static inline int currentSourceId(ExecState *exec)
171 {
172 return exec->currentBody()->sourceId();
173 }
174
currentSourceURL(ExecState * exec)175 static inline const UString ¤tSourceURL(ExecState *exec)
176 {
177 return exec->currentBody()->sourceURL();
178 }
179
throwError(ExecState * exec,ErrorType e,const UString & msg)180 JSValue *Node::throwError(ExecState *exec, ErrorType e, const UString &msg)
181 {
182 return KJS::throwError(exec, e, msg, lineNo(), currentSourceId(exec), currentSourceURL(exec));
183 }
184
throwError(ExecState * exec,ErrorType e,const UString & msg,const Identifier & label)185 JSValue *Node::throwError(ExecState *exec, ErrorType e, const UString &msg, const Identifier &label)
186 {
187 UString message = msg;
188 substitute(message, label.ustring());
189 return KJS::throwError(exec, e, message, lineNo(), currentSourceId(exec), currentSourceURL(exec));
190 }
191
throwUndefinedVariableError(ExecState * exec,const Identifier & ident)192 JSValue *Node::throwUndefinedVariableError(ExecState *exec, const Identifier &ident)
193 {
194 return throwError(exec, ReferenceError, "Cannot find variable: %s", ident);
195 }
196
nodeInsideAllParens()197 Node *Node::nodeInsideAllParens()
198 {
199 return this;
200 }
201
202 class VarDeclVisitor: public NodeVisitor
203 {
204 private:
205 ExecState *m_exec;
206 public:
VarDeclVisitor(ExecState * exec)207 VarDeclVisitor(ExecState *exec) : m_exec(exec)
208 {}
209
visit(Node * node)210 Node *visit(Node *node) override
211 {
212 node->processVarDecl(m_exec);
213
214 //Do not recurse inside function bodies, or things that
215 // syntactically can't contain declarations
216 if (!node->scanForDeclarations()) {
217 return nullptr;
218 }
219
220 return NodeVisitor::visit(node);
221 }
222 };
223
224 class FuncDeclVisitor: public NodeVisitor
225 {
226 private:
227 ExecState *m_exec;
228 public:
FuncDeclVisitor(ExecState * exec)229 FuncDeclVisitor(ExecState *exec) : m_exec(exec)
230 {}
231
visit(Node * node)232 Node *visit(Node *node) override
233 {
234 node->processFuncDecl(m_exec);
235
236 if (!node->scanForDeclarations()) {
237 return nullptr;
238 }
239
240 return NodeVisitor::visit(node);
241 }
242 };
243
processDecls(ExecState * exec)244 void Node::processDecls(ExecState *exec)
245 {
246 VarDeclVisitor vVisit(exec);
247 vVisit.visit(this);
248
249 FuncDeclVisitor fVisit(exec);
250 fVisit.visit(this);
251 }
252
processVarDecl(ExecState *)253 void Node::processVarDecl(ExecState *)
254 {}
255
processFuncDecl(ExecState *)256 void Node::processFuncDecl(ExecState *)
257 {}
258
259 // ------------------------------ NodeVisitor ----------------------------------
visit(Node * node)260 Node *NodeVisitor::visit(Node *node)
261 {
262 node->recurseVisit(this);
263 return nullptr;
264 }
265
266 // ------------------------------ StatementNode --------------------------------
267
StatementNode()268 StatementNode::StatementNode()
269 : m_lastLine(-1)
270 {
271 m_line = -1;
272 }
273
setLoc(int firstLine,int lastLine) const274 void StatementNode::setLoc(int firstLine, int lastLine) const
275 {
276 m_line = firstLine;
277 m_lastLine = lastLine;
278 }
279
hitStatement(ExecState * exec)280 void StatementNode::hitStatement(ExecState *exec)
281 {
282 // The debugger is always non-zero here, since otherwise this won't be involved
283 exec->dynamicInterpreter()->debugger()->reportAtStatement(exec, currentSourceId(exec), firstLine(), lastLine());
284 }
285
286 // ------------------------------ GroupNode ------------------------------------
287
nodeInsideAllParens()288 Node *GroupNode::nodeInsideAllParens()
289 {
290 Node *n = this;
291 do {
292 n = static_cast<GroupNode *>(n)->group.get();
293 } while (n->isGroupNode());
294 return n;
295 }
296
recurseVisit(NodeVisitor * visitor)297 void GroupNode::recurseVisit(NodeVisitor *visitor)
298 {
299 recurseVisitLink(visitor, group);
300 }
301
302 // ------------------------------ ElementNode ----------------------------------
303
breakCycle()304 void ElementNode::breakCycle()
305 {
306 next = nullptr;
307 }
308
recurseVisit(NodeVisitor * visitor)309 void ElementNode::recurseVisit(NodeVisitor *visitor)
310 {
311 recurseVisitLink(visitor, next);
312 recurseVisitLink(visitor, node);
313 }
314
315 // ------------------------------ ArrayNode ------------------------------------
316
recurseVisit(NodeVisitor * visitor)317 void ArrayNode::recurseVisit(NodeVisitor *visitor)
318 {
319 recurseVisitLink(visitor, element);
320 }
321
322 // ------------------------------ ObjectLiteralNode ----------------------------
323
recurseVisit(NodeVisitor * visitor)324 void ObjectLiteralNode::recurseVisit(NodeVisitor *visitor)
325 {
326 recurseVisitLink(visitor, list);
327 }
328
329 // ------------------------------ PropertyListNode -----------------------------
330
breakCycle()331 void PropertyListNode::breakCycle()
332 {
333 next = nullptr;
334 }
335
recurseVisit(NodeVisitor * visitor)336 void PropertyListNode::recurseVisit(NodeVisitor *visitor)
337 {
338 recurseVisitLink(visitor, node);
339 recurseVisitLink(visitor, next);
340 }
341
342 // ------------------------------ PropertyNode -----------------------------
recurseVisit(NodeVisitor * visitor)343 void PropertyNode::recurseVisit(NodeVisitor *visitor)
344 {
345 recurseVisitLink(visitor, name);
346 recurseVisitLink(visitor, assign);
347 }
348
349 // ------------------------------ BracketAccessorNode --------------------------------
350
recurseVisit(NodeVisitor * visitor)351 void BracketAccessorNode::recurseVisit(NodeVisitor *visitor)
352 {
353 recurseVisitLink(visitor, expr1);
354 recurseVisitLink(visitor, expr2);
355 }
356
357 // ------------------------------ DotAccessorNode --------------------------------
358
recurseVisit(NodeVisitor * visitor)359 void DotAccessorNode::recurseVisit(NodeVisitor *visitor)
360 {
361 recurseVisitLink(visitor, expr);
362 }
363
364 // ------------------------------ ArgumentListNode -----------------------------
365
breakCycle()366 void ArgumentListNode::breakCycle()
367 {
368 next = nullptr;
369 }
370
recurseVisit(NodeVisitor * visitor)371 void ArgumentListNode::recurseVisit(NodeVisitor *visitor)
372 {
373 recurseVisitLink(visitor, next);
374 recurseVisitLink(visitor, expr);
375 }
376
377 // ------------------------------ ArgumentsNode --------------------------------
378
recurseVisit(NodeVisitor * visitor)379 void ArgumentsNode::recurseVisit(NodeVisitor *visitor)
380 {
381 recurseVisitLink(visitor, list);
382 }
383
384 // ------------------------------ NewExprNode ----------------------------------
385
recurseVisit(NodeVisitor * visitor)386 void NewExprNode::recurseVisit(NodeVisitor *visitor)
387 {
388 recurseVisitLink(visitor, expr);
389 recurseVisitLink(visitor, args);
390 }
391
392 // ------------------------------ FunctionCallValueNode ------------------------
393
recurseVisit(NodeVisitor * visitor)394 void FunctionCallValueNode::recurseVisit(NodeVisitor *visitor)
395 {
396 recurseVisitLink(visitor, expr);
397 recurseVisitLink(visitor, args);
398 }
399
400 // ------------------------------ FunctionCallRerefenceNode --------------------
401
recurseVisit(NodeVisitor * visitor)402 void FunctionCallReferenceNode::recurseVisit(NodeVisitor *visitor)
403 {
404 recurseVisitLink(visitor, expr);
405 recurseVisitLink(visitor, args);
406 }
407
408 // ------------------------------ PostfixNode ----------------------------------
409
recurseVisit(NodeVisitor * visitor)410 void PostfixNode::recurseVisit(NodeVisitor *visitor)
411 {
412 Node::recurseVisitLink(visitor, m_loc);
413 }
414
415 // ------------------------------ DeleteReferenceNode -------------------------------
416
recurseVisit(NodeVisitor * visitor)417 void DeleteReferenceNode::recurseVisit(NodeVisitor *visitor)
418 {
419 Node::recurseVisitLink(visitor, loc);
420 }
421
422 // ------------------------------ DeleteValueNode -----------------------------------
423
recurseVisit(NodeVisitor * visitor)424 void DeleteValueNode::recurseVisit(NodeVisitor *visitor)
425 {
426 recurseVisitLink(visitor, m_expr);
427 }
428
429 // ------------------------------ VoidNode -------------------------------------
430
recurseVisit(NodeVisitor * visitor)431 void VoidNode::recurseVisit(NodeVisitor *visitor)
432 {
433 recurseVisitLink(visitor, expr);
434 }
435
436 // ------------------------------ TypeOfVarNode -----------------------------------
437
recurseVisit(NodeVisitor * visitor)438 void TypeOfVarNode::recurseVisit(NodeVisitor *visitor)
439 {
440 Node::recurseVisitLink(visitor, loc);
441 }
442
443 // ------------------------------ TypeOfValueNode -----------------------------------
444
recurseVisit(NodeVisitor * visitor)445 void TypeOfValueNode::recurseVisit(NodeVisitor *visitor)
446 {
447 recurseVisitLink(visitor, m_expr);
448 }
449
450 // ------------------------------ PrefixNode ----------------------------------------
451
recurseVisit(NodeVisitor * visitor)452 void PrefixNode::recurseVisit(NodeVisitor *visitor)
453 {
454 Node::recurseVisitLink(visitor, m_loc);
455 }
456
457 // ------------------------------ UnaryPlusNode --------------------------------
458
recurseVisit(NodeVisitor * visitor)459 void UnaryPlusNode::recurseVisit(NodeVisitor *visitor)
460 {
461 recurseVisitLink(visitor, expr);
462 }
463
464 // ------------------------------ NegateNode -----------------------------------
465
recurseVisit(NodeVisitor * visitor)466 void NegateNode::recurseVisit(NodeVisitor *visitor)
467 {
468 recurseVisitLink(visitor, expr);
469 }
470
471 // ------------------------------ BitwiseNotNode -------------------------------
472
recurseVisit(NodeVisitor * visitor)473 void BitwiseNotNode::recurseVisit(NodeVisitor *visitor)
474 {
475 recurseVisitLink(visitor, expr);
476 }
477
478 // ------------------------------ LogicalNotNode -------------------------------
479
recurseVisit(NodeVisitor * visitor)480 void LogicalNotNode::recurseVisit(NodeVisitor *visitor)
481 {
482 recurseVisitLink(visitor, expr);
483 }
484
485 // ------------------------ BinaryOperatorNode -------------------------------
486
recurseVisit(NodeVisitor * visitor)487 void BinaryOperatorNode::recurseVisit(NodeVisitor *visitor)
488 {
489 recurseVisitLink(visitor, expr1);
490 recurseVisitLink(visitor, expr2);
491 }
492
493 // ------------------------------ BinaryLogicalNode ----------------------------
494
recurseVisit(NodeVisitor * visitor)495 void BinaryLogicalNode::recurseVisit(NodeVisitor *visitor)
496 {
497 recurseVisitLink(visitor, expr1);
498 recurseVisitLink(visitor, expr2);
499 }
500
501 // ------------------------------ ConditionalNode ------------------------------
502
recurseVisit(NodeVisitor * visitor)503 void ConditionalNode::recurseVisit(NodeVisitor *visitor)
504 {
505 recurseVisitLink(visitor, logical);
506 recurseVisitLink(visitor, expr1);
507 recurseVisitLink(visitor, expr2);
508 }
509
510 // ------------------------------ AssignNode -----------------------------------
511
recurseVisit(NodeVisitor * visitor)512 void AssignNode::recurseVisit(NodeVisitor *visitor)
513 {
514 Node::recurseVisitLink(visitor, m_loc);
515 Node::recurseVisitLink(visitor, m_right);
516 }
517
518 // ------------------------------ CommaNode ------------------------------------
519
recurseVisit(NodeVisitor * visitor)520 void CommaNode::recurseVisit(NodeVisitor *visitor)
521 {
522 recurseVisitLink(visitor, expr1);
523 recurseVisitLink(visitor, expr2);
524 }
525
526 // ------------------------------ AssignExprNode -------------------------------
527
recurseVisit(NodeVisitor * visitor)528 void AssignExprNode::recurseVisit(NodeVisitor *visitor)
529 {
530 recurseVisitLink(visitor, expr);
531 }
532
533 // ------------------------------ VarDeclNode ----------------------------------
534
VarDeclNode(const Identifier & id,AssignExprNode * in,Type t)535 VarDeclNode::VarDeclNode(const Identifier &id, AssignExprNode *in, Type t)
536 : varType(t), ident(id), init(in)
537 {
538 }
539
540 #if 0
541 // ECMA 12.2
542 JSValue *VarDeclNode::evaluate(ExecState *exec)
543 {
544 JSObject *variable = exec->variableObject();
545
546 JSValue *val;
547 if (init) {
548 val = init->evaluate(exec);
549 KJS_CHECKEXCEPTIONVALUE
550 } else {
551 // already declared? - check with getDirect so you can override
552 // built-in properties of the global object with var declarations.
553 // Also check for 'arguments' property. The 'arguments' cannot be found with
554 // getDirect, because it's created lazily by
555 // ActivationImp::getOwnPropertySlot.
556 // Since variable declarations are always in function scope, 'variable'
557 // will always contain instance of ActivationImp and ActivationImp will
558 // always have 'arguments' property
559 if (variable->getDirect(ident) || ident == exec->propertyNames().arguments) {
560 return 0;
561 }
562 val = jsUndefined();
563 }
564
565 #ifdef KJS_VERBOSE
566 printInfo(exec, (UString("new variable ") + ident.ustring()).cstring().c_str(), val);
567 #endif
568 // We use Internal to bypass all checks in derived objects, e.g. so that
569 // "var location" creates a dynamic property instead of activating window.location.
570 int flags = Internal;
571 if (exec->codeType() != EvalCode) {
572 flags |= DontDelete;
573 }
574 if (varType == VarDeclNode::Constant) {
575 flags |= ReadOnly;
576 }
577 variable->put(exec, ident, val, flags);
578
579 return 0; //No useful value, not a true expr
580 }
581 #endif
582
processVarDecl(ExecState * exec)583 void VarDeclNode::processVarDecl(ExecState *exec)
584 {
585 JSObject *variable = exec->variableObject();
586
587 // First, determine which flags we want to use..
588 int flags = DontDelete;
589 if (varType == VarDeclNode::Constant) {
590 flags |= ReadOnly;
591 }
592
593 // Are we inside a function? If so, we fill in the symbol table
594 switch (exec->codeType()) {
595 case FunctionCode:
596 // Inside a function, we're just computing static information.
597 // so, just fill in the symbol table.
598 exec->currentBody()->addVarDecl(ident, flags, exec);
599 return;
600 case EvalCode:
601 // eval-injected variables can be deleted..
602 flags &= ~DontDelete;
603
604 // If a variable by this name already exists, don't clobber it -
605 // eval may be trying to inject a variable that already exists..
606 if (!variable->hasProperty(exec, ident)) {
607 variable->put(exec, ident, jsUndefined(), flags);
608 // eval injected a new local into scope! Better mark that down,
609 // so that NonLocalResolver stops skipping the local scope
610 variable->setLocalInjected();
611 }
612 break;
613 case GlobalCode:
614 // If a variable by this name already exists, don't clobber it -
615 // ### I am not sue this is needed for GlobalCode
616 if (!variable->hasProperty(exec, ident)) {
617 variable->put(exec, ident, jsUndefined(), flags);
618 }
619 };
620 }
621
recurseVisit(NodeVisitor * visitor)622 void VarDeclNode::recurseVisit(NodeVisitor *visitor)
623 {
624 recurseVisitLink(visitor, init);
625 }
626
627 // ------------------------------ VarDeclListNode ------------------------------
628
breakCycle()629 void VarDeclListNode::breakCycle()
630 {
631 next = nullptr;
632 }
633
recurseVisit(NodeVisitor * visitor)634 void VarDeclListNode::recurseVisit(NodeVisitor *visitor)
635 {
636 recurseVisitLink(visitor, var);
637 recurseVisitLink(visitor, next);
638 }
639
640 // ------------------------------ VarStatementNode -----------------------------
641
recurseVisit(NodeVisitor * visitor)642 void VarStatementNode::recurseVisit(NodeVisitor *visitor)
643 {
644 recurseVisitLink(visitor, next);
645 }
646
647 // ------------------------------ BlockNode ------------------------------------
648
BlockNode(SourceElementsNode * s)649 BlockNode::BlockNode(SourceElementsNode *s)
650 {
651 if (s) {
652 source = s->next.release();
653 Parser::removeNodeCycle(source.get());
654 setLoc(s->firstLine(), s->lastLine());
655 } else {
656 source = nullptr;
657 }
658 }
659
recurseVisit(NodeVisitor * visitor)660 void BlockNode::recurseVisit(NodeVisitor *visitor)
661 {
662 recurseVisitLink(visitor, source);
663 }
664
665 // ------------------------------ ExprStatementNode ----------------------------
666
recurseVisit(NodeVisitor * visitor)667 void ExprStatementNode::recurseVisit(NodeVisitor *visitor)
668 {
669 recurseVisitLink(visitor, expr);
670 }
671
672 // ------------------------------ IfNode ---------------------------------------
673
recurseVisit(NodeVisitor * visitor)674 void IfNode::recurseVisit(NodeVisitor *visitor)
675 {
676 recurseVisitLink(visitor, expr);
677 recurseVisitLink(visitor, statement1);
678 recurseVisitLink(visitor, statement2);
679 }
680
681 // ------------------------------ DoWhileNode ----------------------------------
682
recurseVisit(NodeVisitor * visitor)683 void DoWhileNode::recurseVisit(NodeVisitor *visitor)
684 {
685 recurseVisitLink(visitor, expr);
686 recurseVisitLink(visitor, statement);
687 }
688
689 // ------------------------------ WhileNode ------------------------------------
690
recurseVisit(NodeVisitor * visitor)691 void WhileNode::recurseVisit(NodeVisitor *visitor)
692 {
693 recurseVisitLink(visitor, expr);
694 recurseVisitLink(visitor, statement);
695 }
696
697 // ------------------------------ ForNode --------------------------------------
698
recurseVisit(NodeVisitor * visitor)699 void ForNode::recurseVisit(NodeVisitor *visitor)
700 {
701 recurseVisitLink(visitor, expr1);
702 recurseVisitLink(visitor, expr2);
703 recurseVisitLink(visitor, expr3);
704 recurseVisitLink(visitor, statement);
705 }
706
707 // ------------------------------ ForInNode ------------------------------------
708
ForInNode(Node * l,Node * e,StatementNode * s)709 ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
710 : init(nullptr), lexpr(l), expr(e), varDecl(nullptr), statement(s)
711 {
712 }
713
ForInNode(const Identifier & i,AssignExprNode * in,Node * e,StatementNode * s)714 ForInNode::ForInNode(const Identifier &i, AssignExprNode *in, Node *e, StatementNode *s)
715 : ident(i), init(in), expr(e), statement(s)
716 {
717 // for( var foo = bar in baz )
718 varDecl = new VarDeclNode(ident, init.get(), VarDeclNode::Variable);
719 lexpr = new VarAccessNode(ident);
720 }
721
recurseVisit(NodeVisitor * visitor)722 void ForInNode::recurseVisit(NodeVisitor *visitor)
723 {
724 recurseVisitLink(visitor, init);
725 recurseVisitLink(visitor, lexpr);
726 recurseVisitLink(visitor, expr);
727 recurseVisitLink(visitor, varDecl);
728 recurseVisitLink(visitor, statement);
729 }
730
731 // ------------------------------ ReturnNode -----------------------------------
732
recurseVisit(NodeVisitor * visitor)733 void ReturnNode::recurseVisit(NodeVisitor *visitor)
734 {
735 recurseVisitLink(visitor, value);
736 }
737
738 // ------------------------------ WithNode -------------------------------------
739
recurseVisit(NodeVisitor * visitor)740 void WithNode::recurseVisit(NodeVisitor *visitor)
741 {
742 recurseVisitLink(visitor, expr);
743 recurseVisitLink(visitor, statement);
744 }
745
746 // ------------------------------ CaseClauseNode -------------------------------
747
recurseVisit(NodeVisitor * visitor)748 void CaseClauseNode::recurseVisit(NodeVisitor *visitor)
749 {
750 recurseVisitLink(visitor, expr);
751 recurseVisitLink(visitor, source);
752 }
753
754 // ------------------------------ ClauseListNode -------------------------------
755
breakCycle()756 void ClauseListNode::breakCycle()
757 {
758 next = nullptr;
759 }
760
recurseVisit(NodeVisitor * visitor)761 void ClauseListNode::recurseVisit(NodeVisitor *visitor)
762 {
763 recurseVisitLink(visitor, clause);
764 recurseVisitLink(visitor, next);
765 }
766
767 // ------------------------------ CaseBlockNode --------------------------------
768
CaseBlockNode(ClauseListNode * l1,CaseClauseNode * d,ClauseListNode * l2)769 CaseBlockNode::CaseBlockNode(ClauseListNode *l1, CaseClauseNode *d,
770 ClauseListNode *l2)
771 {
772 if (l1) {
773 list1 = l1->next.release();
774 Parser::removeNodeCycle(list1.get());
775 } else {
776 list1 = nullptr;
777 }
778
779 def = d;
780
781 if (l2) {
782 list2 = l2->next.release();
783 Parser::removeNodeCycle(list2.get());
784 } else {
785 list2 = nullptr;
786 }
787 }
788
recurseVisit(NodeVisitor * visitor)789 void CaseBlockNode::recurseVisit(NodeVisitor *visitor)
790 {
791 recurseVisitLink(visitor, list1);
792 recurseVisitLink(visitor, def);
793 recurseVisitLink(visitor, list2);
794 }
795
796 // ------------------------------ SwitchNode -----------------------------------
797
recurseVisit(NodeVisitor * visitor)798 void SwitchNode::recurseVisit(NodeVisitor *visitor)
799 {
800 recurseVisitLink(visitor, expr);
801 recurseVisitLink(visitor, block);
802 }
803
804 // ------------------------------ LabelNode ------------------------------------
805
recurseVisit(NodeVisitor * visitor)806 void LabelNode::recurseVisit(NodeVisitor *visitor)
807 {
808 recurseVisitLink(visitor, statement);
809 }
810
811 // ------------------------------ ThrowNode ------------------------------------
812
recurseVisit(NodeVisitor * visitor)813 void ThrowNode::recurseVisit(NodeVisitor *visitor)
814 {
815 recurseVisitLink(visitor, expr);
816 }
817
818 // ------------------------------ TryNode --------------------------------------
819
recurseVisit(NodeVisitor * visitor)820 void TryNode::recurseVisit(NodeVisitor *visitor)
821 {
822 recurseVisitLink(visitor, tryBlock);
823 recurseVisitLink(visitor, catchBlock);
824 recurseVisitLink(visitor, finallyBlock);
825 }
826
827 // ------------------------------ ParameterNode --------------------------------
828
breakCycle()829 void ParameterNode::breakCycle()
830 {
831 next = nullptr;
832 }
833
recurseVisit(NodeVisitor * visitor)834 void ParameterNode::recurseVisit(NodeVisitor *visitor)
835 {
836 recurseVisitLink(visitor, next);
837 }
838
839 // ------------------------------ FunctionBodyNode -----------------------------
840
FunctionBodyNode(SourceElementsNode * s)841 FunctionBodyNode::FunctionBodyNode(SourceElementsNode *s)
842 : BlockNode(s)
843 , m_sourceURL(lexer().sourceURL())
844 , m_sourceId(parser().sourceId())
845 , m_compType(NotCompiled)
846 , m_flags(parser().popFunctionContext())
847 {
848 setLoc(-1, -1);
849 }
850
addVarDecl(const Identifier & ident,int attr,ExecState * exec)851 void FunctionBodyNode::addVarDecl(const Identifier &ident, int attr, ExecState *exec)
852 {
853 // There is one nasty special case: ignore a 'var' declaration of 'arguments';
854 // it effectively doesn't do anything since the magic 'arguments' is already
855 // in scope anyway, and if we allocated a local, we would have to worry about
856 // keeping track of whether it was initialized or not on what is supposed to be the
857 // fast path. So we just make this go through the property map instead.
858 // Note that this does not matter for parameters or function declarations,
859 // since those overwrite the magic 'arguments' anyway.
860 if (ident == exec->propertyNames().arguments) {
861 return;
862 }
863
864 (void)addSymbol(ident, attr);
865 }
866
addFunDecl(const Identifier & ident,int attr,FuncDeclNode * funcDecl)867 void FunctionBodyNode::addFunDecl(const Identifier &ident, int attr, FuncDeclNode *funcDecl)
868 {
869 m_functionLocals.append(addSymbol(ident, attr, funcDecl));
870 }
871
reserveSlot(size_t id,bool shouldMark)872 void FunctionBodyNode::reserveSlot(size_t id, bool shouldMark)
873 {
874 ASSERT(id == m_symbolList.size());
875 m_symbolList.append(SymbolInfo(shouldMark ? 0 : DontMark, nullptr));
876 }
877
addSymbol(const Identifier & ident,int flags,FuncDeclNode * funcDecl)878 size_t FunctionBodyNode::addSymbol(const Identifier &ident, int flags, FuncDeclNode *funcDecl)
879 {
880 // We get symbols in the order specified in 10.1.3, but sometimes
881 // the later ones are supposed to lose. This -mostly- does not
882 // matter for us --- we primarily concern ourselves with name/ID
883 // mapping, but there is an issue of attributes and funcDecl's.
884 // However, the only flag that matters here is ReadOnly --
885 // everything else just has DontDelete set; and it's from const,
886 // so we can just ignore it on repetitions, since var/const should lose
887 // and are at the end.
888 //
889 // And for funcDecl, since functions win over everything, we always set it if non-zero
890 size_t oldId = m_symbolTable.get(ident.ustring().rep());
891 if (oldId != missingSymbolMarker()) {
892 if (funcDecl) {
893 m_symbolList[oldId].funcDecl = funcDecl;
894 }
895 return oldId;
896 }
897
898 size_t id = m_symbolList.size(); //First entry gets 0, etc.
899 m_symbolTable.set(ident.ustring().rep(), id);
900 m_symbolList.append(SymbolInfo(flags, funcDecl));
901 return id;
902 }
903
addSymbolOverwriteID(size_t id,const Identifier & ident,int flags)904 void FunctionBodyNode::addSymbolOverwriteID(size_t id, const Identifier &ident, int flags)
905 {
906 ASSERT(id == m_symbolList.size());
907
908 // Remove previous one, if any
909 size_t oldId = m_symbolTable.get(ident.ustring().rep());
910 if (oldId != missingSymbolMarker()) {
911 m_symbolList[oldId].attr = DontMark;
912 }
913
914 // Add a new one
915 m_symbolTable.set(ident.ustring().rep(), id);
916 m_symbolList.append(SymbolInfo(flags, nullptr));
917 }
918
addParam(const Identifier & ident)919 void FunctionBodyNode::addParam(const Identifier &ident)
920 {
921 m_paramList.append(ident);
922 }
923
execute(ExecState * exec)924 Completion FunctionBodyNode::execute(ExecState *exec)
925 {
926 CodeType ctype = exec->codeType();
927 CompileType cmpType = exec->dynamicInterpreter()->debugger() ? Debug : Release;
928 compileIfNeeded(ctype, cmpType);
929 ASSERT(ctype != FunctionCode);
930
931 LocalStorage *store = new LocalStorage();
932 LocalStorageEntry *regs;
933
934 // Allocate enough space, and make sure to initialize things so we don't mark garbage
935 store->resize(m_symbolList.size());
936 regs = store->data();
937 for (size_t c = 0; c < m_symbolList.size(); ++c) {
938 regs[c].val.valueVal = jsUndefined();
939 regs[c].attributes = m_symbolList[c].attr;
940 }
941
942 exec->initLocalStorage(regs, m_symbolList.size());
943
944 JSValue *val = Machine::runBlock(exec, m_compiledCode);
945
946 Completion result;
947 if (exec->hadException()) {
948 result = Completion(Throw, exec->exception());
949 } else {
950 result = Completion(Normal, val);
951 }
952
953 exec->initLocalStorage(nullptr, 0);
954 delete store;
955 exec->clearException();
956
957 return result;
958 }
959
compile(CodeType ctype,CompileType compType)960 void FunctionBodyNode::compile(CodeType ctype, CompileType compType)
961 {
962 m_compType = compType;
963
964 CompileState comp(ctype, compType, this, m_symbolList.size());
965 generateExecCode(&comp);
966 m_tearOffAtEnd = comp.needsClosures();
967
968 #if 0
969 fprintf(stderr, "\n\n");
970 fprintf(stderr, "\n---------------------------------\n\n");
971 fprintf(stderr, "%s", toString().ascii());
972 fprintf(stderr, "\n---------------------------------\n\n");
973 CodeGen::disassembleBlock(m_compiledCode);
974 fprintf(stderr, "\n---------------------------------\n\n");
975 #endif
976 }
977
978 // ------------------------------ FuncDeclNode ---------------------------------
979
980 // ECMA 13
processFuncDecl(ExecState * exec)981 void FuncDeclNode::processFuncDecl(ExecState *exec)
982 {
983 // See whether we just need to fill in the symbol table,
984 // or actually fiddle with objects.
985 int flags = Internal | DontDelete;
986 switch (exec->codeType()) {
987 case FunctionCode:
988 // Inside a function, just need symbol info
989 exec->currentBody()->addFunDecl(ident, flags, this);
990 return;
991 case EvalCode:
992 // eval-injected symbols can be deleted...
993 flags &= ~DontDelete;
994
995 // eval injected a new local into scope! Better mark that down,
996 // so that NonLocalResolver stops skipping the local scope
997 exec->variableObject()->setLocalInjected();
998
999 // fallthrough intentional
1000 case GlobalCode:
1001 exec->variableObject()->put(exec, ident, makeFunctionObject(exec), flags);
1002 };
1003 }
1004
addParams()1005 void FuncDeclNode::addParams()
1006 {
1007 for (ParameterNode *p = param.get(); p != nullptr; p = p->nextParam()) {
1008 body->addParam(p->ident());
1009 }
1010 }
1011
makeFunctionObject(ExecState * exec)1012 FunctionImp *FuncDeclNode::makeFunctionObject(ExecState *exec)
1013 {
1014 // TODO: let this be an object with [[Class]] property "Function"
1015 FunctionImp *func = new FunctionImp(exec, ident, body.get(), exec->scopeChain());
1016
1017 JSObject *proto = exec->lexicalInterpreter()->builtinObject()->construct(exec, List::empty());
1018 proto->put(exec, exec->propertyNames().constructor, func, DontEnum);
1019 // ECMA Edition 5.1r6 - 15.3.5.2 - [[Writable]]: true, [[Enumerable]]: false, [[Configurable]]: false
1020 func->put(exec, exec->propertyNames().prototype, proto, Internal | DontDelete | DontEnum);
1021
1022 func->put(exec, exec->propertyNames().length, jsNumber(body->numParams()), ReadOnly | DontDelete | DontEnum);
1023
1024 return func;
1025 }
1026
recurseVisit(NodeVisitor * visitor)1027 void FuncDeclNode::recurseVisit(NodeVisitor *visitor)
1028 {
1029 recurseVisitLink(visitor, param);
1030 recurseVisitLink(visitor, body);
1031 }
1032
1033 // ------------------------------ FuncExprNode ---------------------------------
1034
addParams()1035 void FuncExprNode::addParams()
1036 {
1037 for (ParameterNode *p = param.get(); p != nullptr; p = p->nextParam()) {
1038 body->addParam(p->ident());
1039 }
1040 }
1041
recurseVisit(NodeVisitor * visitor)1042 void FuncExprNode::recurseVisit(NodeVisitor *visitor)
1043 {
1044 recurseVisitLink(visitor, param);
1045 recurseVisitLink(visitor, body);
1046 }
1047
1048 // ------------------------------ SourceElementsNode ---------------------------
1049
SourceElementsNode(StatementNode * s1)1050 SourceElementsNode::SourceElementsNode(StatementNode *s1)
1051 : node(s1), next(this)
1052 {
1053 Parser::noteNodeCycle(this);
1054 setLoc(s1->firstLine(), s1->lastLine());
1055 }
1056
SourceElementsNode(SourceElementsNode * s1,StatementNode * s2)1057 SourceElementsNode::SourceElementsNode(SourceElementsNode *s1, StatementNode *s2)
1058 : node(s2), next(s1->next)
1059 {
1060 s1->next = this;
1061 setLoc(s1->firstLine(), s2->lastLine());
1062 }
1063
breakCycle()1064 void SourceElementsNode::breakCycle()
1065 {
1066 next = nullptr;
1067 }
1068
recurseVisit(NodeVisitor * visitor)1069 void SourceElementsNode::recurseVisit(NodeVisitor *visitor)
1070 {
1071 recurseVisitLink(visitor, node);
1072 recurseVisitLink(visitor, next);
1073 }
1074
1075 // ------------------------------ ProgramNode ----------------------------------
1076
ProgramNode(SourceElementsNode * s)1077 ProgramNode::ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s)
1078 {
1079 }
1080
1081 // ------------------------------ PackageNameNode ------------------------------
recurseVisit(NodeVisitor * visitor)1082 void PackageNameNode::recurseVisit(NodeVisitor *visitor)
1083 {
1084 recurseVisitLink(visitor, names);
1085 }
1086
loadSymbol(ExecState * exec,bool wildcard)1087 Completion PackageNameNode::loadSymbol(ExecState *exec, bool wildcard)
1088 {
1089 Package *basePackage;
1090 JSObject *baseObject;
1091 if (names) {
1092 PackageObject *pobj = names->resolvePackage(exec);
1093 if (pobj == nullptr) {
1094 return Completion(Normal);
1095 }
1096 basePackage = pobj->package();
1097 baseObject = pobj;
1098 } else {
1099 Interpreter *ip = exec->lexicalInterpreter();
1100 basePackage = ip->globalPackage();
1101 baseObject = ip->globalObject();
1102 }
1103
1104 if (wildcard) {
1105 // if a .* is specified the last identifier should
1106 // denote another package name
1107 PackageObject *pobj = resolvePackage(exec, baseObject, basePackage);
1108 if (!pobj) {
1109 return Completion(Normal);
1110 }
1111 basePackage = pobj->package();
1112 baseObject = pobj;
1113 basePackage->loadAllSymbols(exec, baseObject);
1114 } else {
1115 basePackage->loadSymbol(exec, baseObject, id);
1116 }
1117
1118 return Completion(Normal);
1119 }
1120
resolvePackage(ExecState * exec)1121 PackageObject *PackageNameNode::resolvePackage(ExecState *exec)
1122 {
1123 JSObject *baseObject;
1124 Package *basePackage;
1125 if (names) {
1126 PackageObject *basePackageObject = names->resolvePackage(exec);
1127 if (basePackageObject == nullptr) {
1128 return nullptr;
1129 }
1130 baseObject = basePackageObject;
1131 basePackage = basePackageObject->package();
1132 } else {
1133 // first identifier is looked up in global object
1134 Interpreter *ip = exec->lexicalInterpreter();
1135 baseObject = ip->globalObject();
1136 basePackage = ip->globalPackage();
1137 }
1138
1139 return resolvePackage(exec, baseObject, basePackage);
1140 }
1141
resolvePackage(ExecState * exec,JSObject * baseObject,Package * basePackage)1142 PackageObject *PackageNameNode::resolvePackage(ExecState *exec,
1143 JSObject *baseObject,
1144 Package *basePackage)
1145 {
1146 PackageObject *res = nullptr;
1147
1148 // Let's see whether the package was already resolved previously.
1149 JSValue *v = baseObject->get(exec, id);
1150 if (v && !JSValue::isUndefined(v)) {
1151 if (!JSValue::isObject(v)) {
1152 // Symbol conflict
1153 throwError(exec, GeneralError, "Invalid type of package %s", id);
1154 return nullptr;
1155 }
1156 res = static_cast<PackageObject *>(v);
1157 } else {
1158 UString err;
1159 Package *newBase = basePackage->loadSubPackage(id, &err);
1160 if (newBase == nullptr) {
1161 if (err.isEmpty()) {
1162 throwError(exec, GeneralError, "Package not found");
1163 } else {
1164 throwError(exec, GeneralError, err);
1165 }
1166 return nullptr;
1167 }
1168 res = new PackageObject(newBase);
1169 baseObject->put(exec, id, res);
1170 }
1171
1172 return res;
1173 }
1174
processVarDecl(ExecState * exec)1175 void ImportStatement::processVarDecl(ExecState *exec)
1176 {
1177 // error out if package support is not activated
1178 Package *glob = exec->lexicalInterpreter()->globalPackage();
1179 if (!glob) {
1180 throwError(exec, GeneralError,
1181 "Package support disabled. Import failed.");
1182 return;
1183 }
1184
1185 // also error out if not used on top-level
1186 if (exec->codeType() != GlobalCode) {
1187 throwError(exec, GeneralError,
1188 "Package imports may only occur at top level.");
1189 return;
1190 }
1191
1192 name->loadSymbol(exec, wld);
1193 }
1194
recurseVisit(NodeVisitor * visitor)1195 void ImportStatement::recurseVisit(NodeVisitor *visitor)
1196 {
1197 recurseVisitLink(visitor, name);
1198 }
1199
1200 } //namespace KJS
1201