KJS

nodes.cpp
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, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
6  * Copyright (C) 2007 Maksim Orlovich ([email protected])
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;
57  ~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 
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 
83 Node::~Node()
84 {
85 #ifndef NDEBUG
86  --NodeCounter::count;
87 #endif
88 }
89 
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 
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 
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 
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 
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 
170 static inline int currentSourceId(ExecState *exec)
171 {
172  return exec->currentBody()->sourceId();
173 }
174 
175 static inline const UString &currentSourceURL(ExecState *exec)
176 {
177  return exec->currentBody()->sourceURL();
178 }
179 
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 
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 
192 JSValue *Node::throwUndefinedVariableError(ExecState *exec, const Identifier &ident)
193 {
194  return throwError(exec, ReferenceError, "Cannot find variable: %s", ident);
195 }
196 
197 Node *Node::nodeInsideAllParens()
198 {
199  return this;
200 }
201 
202 class VarDeclVisitor: public NodeVisitor
203 {
204 private:
205  ExecState *m_exec;
206 public:
207  VarDeclVisitor(ExecState *exec) : m_exec(exec)
208  {}
209 
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:
229  FuncDeclVisitor(ExecState *exec) : m_exec(exec)
230  {}
231 
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 
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 
253 void Node::processVarDecl(ExecState *)
254 {}
255 
256 void Node::processFuncDecl(ExecState *)
257 {}
258 
259 // ------------------------------ NodeVisitor ----------------------------------
260 Node *NodeVisitor::visit(Node *node)
261 {
262  node->recurseVisit(this);
263  return nullptr;
264 }
265 
266 // ------------------------------ StatementNode --------------------------------
267 
268 StatementNode::StatementNode()
269  : m_lastLine(-1)
270 {
271  m_line = -1;
272 }
273 
274 void StatementNode::setLoc(int firstLine, int lastLine) const
275 {
276  m_line = firstLine;
277  m_lastLine = lastLine;
278 }
279 
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 
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 
297 void GroupNode::recurseVisit(NodeVisitor *visitor)
298 {
299  recurseVisitLink(visitor, group);
300 }
301 
302 // ------------------------------ ElementNode ----------------------------------
303 
304 void ElementNode::breakCycle()
305 {
306  next = nullptr;
307 }
308 
309 void ElementNode::recurseVisit(NodeVisitor *visitor)
310 {
311  recurseVisitLink(visitor, next);
312  recurseVisitLink(visitor, node);
313 }
314 
315 // ------------------------------ ArrayNode ------------------------------------
316 
317 void ArrayNode::recurseVisit(NodeVisitor *visitor)
318 {
319  recurseVisitLink(visitor, element);
320 }
321 
322 // ------------------------------ ObjectLiteralNode ----------------------------
323 
324 void ObjectLiteralNode::recurseVisit(NodeVisitor *visitor)
325 {
326  recurseVisitLink(visitor, list);
327 }
328 
329 // ------------------------------ PropertyListNode -----------------------------
330 
331 void PropertyListNode::breakCycle()
332 {
333  next = nullptr;
334 }
335 
336 void PropertyListNode::recurseVisit(NodeVisitor *visitor)
337 {
338  recurseVisitLink(visitor, node);
339  recurseVisitLink(visitor, next);
340 }
341 
342 // ------------------------------ PropertyNode -----------------------------
343 void PropertyNode::recurseVisit(NodeVisitor *visitor)
344 {
345  recurseVisitLink(visitor, name);
346  recurseVisitLink(visitor, assign);
347 }
348 
349 // ------------------------------ BracketAccessorNode --------------------------------
350 
351 void BracketAccessorNode::recurseVisit(NodeVisitor *visitor)
352 {
353  recurseVisitLink(visitor, expr1);
354  recurseVisitLink(visitor, expr2);
355 }
356 
357 // ------------------------------ DotAccessorNode --------------------------------
358 
359 void DotAccessorNode::recurseVisit(NodeVisitor *visitor)
360 {
361  recurseVisitLink(visitor, expr);
362 }
363 
364 // ------------------------------ ArgumentListNode -----------------------------
365 
366 void ArgumentListNode::breakCycle()
367 {
368  next = nullptr;
369 }
370 
371 void ArgumentListNode::recurseVisit(NodeVisitor *visitor)
372 {
373  recurseVisitLink(visitor, next);
374  recurseVisitLink(visitor, expr);
375 }
376 
377 // ------------------------------ ArgumentsNode --------------------------------
378 
379 void ArgumentsNode::recurseVisit(NodeVisitor *visitor)
380 {
381  recurseVisitLink(visitor, list);
382 }
383 
384 // ------------------------------ NewExprNode ----------------------------------
385 
386 void NewExprNode::recurseVisit(NodeVisitor *visitor)
387 {
388  recurseVisitLink(visitor, expr);
389  recurseVisitLink(visitor, args);
390 }
391 
392 // ------------------------------ FunctionCallValueNode ------------------------
393 
394 void FunctionCallValueNode::recurseVisit(NodeVisitor *visitor)
395 {
396  recurseVisitLink(visitor, expr);
397  recurseVisitLink(visitor, args);
398 }
399 
400 // ------------------------------ FunctionCallRerefenceNode --------------------
401 
402 void FunctionCallReferenceNode::recurseVisit(NodeVisitor *visitor)
403 {
404  recurseVisitLink(visitor, expr);
405  recurseVisitLink(visitor, args);
406 }
407 
408 // ------------------------------ PostfixNode ----------------------------------
409 
410 void PostfixNode::recurseVisit(NodeVisitor *visitor)
411 {
412  Node::recurseVisitLink(visitor, m_loc);
413 }
414 
415 // ------------------------------ DeleteReferenceNode -------------------------------
416 
417 void DeleteReferenceNode::recurseVisit(NodeVisitor *visitor)
418 {
419  Node::recurseVisitLink(visitor, loc);
420 }
421 
422 // ------------------------------ DeleteValueNode -----------------------------------
423 
424 void DeleteValueNode::recurseVisit(NodeVisitor *visitor)
425 {
426  recurseVisitLink(visitor, m_expr);
427 }
428 
429 // ------------------------------ VoidNode -------------------------------------
430 
431 void VoidNode::recurseVisit(NodeVisitor *visitor)
432 {
433  recurseVisitLink(visitor, expr);
434 }
435 
436 // ------------------------------ TypeOfVarNode -----------------------------------
437 
438 void TypeOfVarNode::recurseVisit(NodeVisitor *visitor)
439 {
440  Node::recurseVisitLink(visitor, loc);
441 }
442 
443 // ------------------------------ TypeOfValueNode -----------------------------------
444 
445 void TypeOfValueNode::recurseVisit(NodeVisitor *visitor)
446 {
447  recurseVisitLink(visitor, m_expr);
448 }
449 
450 // ------------------------------ PrefixNode ----------------------------------------
451 
452 void PrefixNode::recurseVisit(NodeVisitor *visitor)
453 {
454  Node::recurseVisitLink(visitor, m_loc);
455 }
456 
457 // ------------------------------ UnaryPlusNode --------------------------------
458 
459 void UnaryPlusNode::recurseVisit(NodeVisitor *visitor)
460 {
461  recurseVisitLink(visitor, expr);
462 }
463 
464 // ------------------------------ NegateNode -----------------------------------
465 
466 void NegateNode::recurseVisit(NodeVisitor *visitor)
467 {
468  recurseVisitLink(visitor, expr);
469 }
470 
471 // ------------------------------ BitwiseNotNode -------------------------------
472 
473 void BitwiseNotNode::recurseVisit(NodeVisitor *visitor)
474 {
475  recurseVisitLink(visitor, expr);
476 }
477 
478 // ------------------------------ LogicalNotNode -------------------------------
479 
480 void LogicalNotNode::recurseVisit(NodeVisitor *visitor)
481 {
482  recurseVisitLink(visitor, expr);
483 }
484 
485 // ------------------------ BinaryOperatorNode -------------------------------
486 
487 void BinaryOperatorNode::recurseVisit(NodeVisitor *visitor)
488 {
489  recurseVisitLink(visitor, expr1);
490  recurseVisitLink(visitor, expr2);
491 }
492 
493 // ------------------------------ BinaryLogicalNode ----------------------------
494 
495 void BinaryLogicalNode::recurseVisit(NodeVisitor *visitor)
496 {
497  recurseVisitLink(visitor, expr1);
498  recurseVisitLink(visitor, expr2);
499 }
500 
501 // ------------------------------ ConditionalNode ------------------------------
502 
503 void ConditionalNode::recurseVisit(NodeVisitor *visitor)
504 {
505  recurseVisitLink(visitor, logical);
506  recurseVisitLink(visitor, expr1);
507  recurseVisitLink(visitor, expr2);
508 }
509 
510 // ------------------------------ AssignNode -----------------------------------
511 
512 void AssignNode::recurseVisit(NodeVisitor *visitor)
513 {
514  Node::recurseVisitLink(visitor, m_loc);
515  Node::recurseVisitLink(visitor, m_right);
516 }
517 
518 // ------------------------------ CommaNode ------------------------------------
519 
520 void CommaNode::recurseVisit(NodeVisitor *visitor)
521 {
522  recurseVisitLink(visitor, expr1);
523  recurseVisitLink(visitor, expr2);
524 }
525 
526 // ------------------------------ AssignExprNode -------------------------------
527 
528 void AssignExprNode::recurseVisit(NodeVisitor *visitor)
529 {
530  recurseVisitLink(visitor, expr);
531 }
532 
533 // ------------------------------ VarDeclNode ----------------------------------
534 
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 
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 
622 void VarDeclNode::recurseVisit(NodeVisitor *visitor)
623 {
624  recurseVisitLink(visitor, init);
625 }
626 
627 // ------------------------------ VarDeclListNode ------------------------------
628 
629 void VarDeclListNode::breakCycle()
630 {
631  next = nullptr;
632 }
633 
634 void VarDeclListNode::recurseVisit(NodeVisitor *visitor)
635 {
636  recurseVisitLink(visitor, var);
637  recurseVisitLink(visitor, next);
638 }
639 
640 // ------------------------------ VarStatementNode -----------------------------
641 
642 void VarStatementNode::recurseVisit(NodeVisitor *visitor)
643 {
644  recurseVisitLink(visitor, next);
645 }
646 
647 // ------------------------------ BlockNode ------------------------------------
648 
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 
660 void BlockNode::recurseVisit(NodeVisitor *visitor)
661 {
662  recurseVisitLink(visitor, source);
663 }
664 
665 // ------------------------------ ExprStatementNode ----------------------------
666 
667 void ExprStatementNode::recurseVisit(NodeVisitor *visitor)
668 {
669  recurseVisitLink(visitor, expr);
670 }
671 
672 // ------------------------------ IfNode ---------------------------------------
673 
674 void IfNode::recurseVisit(NodeVisitor *visitor)
675 {
676  recurseVisitLink(visitor, expr);
677  recurseVisitLink(visitor, statement1);
678  recurseVisitLink(visitor, statement2);
679 }
680 
681 // ------------------------------ DoWhileNode ----------------------------------
682 
683 void DoWhileNode::recurseVisit(NodeVisitor *visitor)
684 {
685  recurseVisitLink(visitor, expr);
686  recurseVisitLink(visitor, statement);
687 }
688 
689 // ------------------------------ WhileNode ------------------------------------
690 
691 void WhileNode::recurseVisit(NodeVisitor *visitor)
692 {
693  recurseVisitLink(visitor, expr);
694  recurseVisitLink(visitor, statement);
695 }
696 
697 // ------------------------------ ForNode --------------------------------------
698 
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 
709 ForInNode::ForInNode(Node *l, Node *e, StatementNode *s)
710  : init(nullptr), lexpr(l), expr(e), varDecl(nullptr), statement(s)
711 {
712 }
713 
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 
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 
733 void ReturnNode::recurseVisit(NodeVisitor *visitor)
734 {
735  recurseVisitLink(visitor, value);
736 }
737 
738 // ------------------------------ WithNode -------------------------------------
739 
740 void WithNode::recurseVisit(NodeVisitor *visitor)
741 {
742  recurseVisitLink(visitor, expr);
743  recurseVisitLink(visitor, statement);
744 }
745 
746 // ------------------------------ CaseClauseNode -------------------------------
747 
748 void CaseClauseNode::recurseVisit(NodeVisitor *visitor)
749 {
750  recurseVisitLink(visitor, expr);
751  recurseVisitLink(visitor, source);
752 }
753 
754 // ------------------------------ ClauseListNode -------------------------------
755 
756 void ClauseListNode::breakCycle()
757 {
758  next = nullptr;
759 }
760 
761 void ClauseListNode::recurseVisit(NodeVisitor *visitor)
762 {
763  recurseVisitLink(visitor, clause);
764  recurseVisitLink(visitor, next);
765 }
766 
767 // ------------------------------ CaseBlockNode --------------------------------
768 
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 
789 void CaseBlockNode::recurseVisit(NodeVisitor *visitor)
790 {
791  recurseVisitLink(visitor, list1);
792  recurseVisitLink(visitor, def);
793  recurseVisitLink(visitor, list2);
794 }
795 
796 // ------------------------------ SwitchNode -----------------------------------
797 
798 void SwitchNode::recurseVisit(NodeVisitor *visitor)
799 {
800  recurseVisitLink(visitor, expr);
801  recurseVisitLink(visitor, block);
802 }
803 
804 // ------------------------------ LabelNode ------------------------------------
805 
806 void LabelNode::recurseVisit(NodeVisitor *visitor)
807 {
808  recurseVisitLink(visitor, statement);
809 }
810 
811 // ------------------------------ ThrowNode ------------------------------------
812 
813 void ThrowNode::recurseVisit(NodeVisitor *visitor)
814 {
815  recurseVisitLink(visitor, expr);
816 }
817 
818 // ------------------------------ TryNode --------------------------------------
819 
820 void TryNode::recurseVisit(NodeVisitor *visitor)
821 {
822  recurseVisitLink(visitor, tryBlock);
823  recurseVisitLink(visitor, catchBlock);
824  recurseVisitLink(visitor, finallyBlock);
825 }
826 
827 // ------------------------------ ParameterNode --------------------------------
828 
829 void ParameterNode::breakCycle()
830 {
831  next = nullptr;
832 }
833 
834 void ParameterNode::recurseVisit(NodeVisitor *visitor)
835 {
836  recurseVisitLink(visitor, next);
837 }
838 
839 // ------------------------------ FunctionBodyNode -----------------------------
840 
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 
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 
867 void FunctionBodyNode::addFunDecl(const Identifier &ident, int attr, FuncDeclNode *funcDecl)
868 {
869  m_functionLocals.append(addSymbol(ident, attr, funcDecl));
870 }
871 
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 
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 
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 
919 void FunctionBodyNode::addParam(const Identifier &ident)
920 {
921  m_paramList.append(ident);
922 }
923 
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 
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
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 
1005 void FuncDeclNode::addParams()
1006 {
1007  for (ParameterNode *p = param.get(); p != nullptr; p = p->nextParam()) {
1008  body->addParam(p->ident());
1009  }
1010 }
1011 
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 
1027 void FuncDeclNode::recurseVisit(NodeVisitor *visitor)
1028 {
1029  recurseVisitLink(visitor, param);
1030  recurseVisitLink(visitor, body);
1031 }
1032 
1033 // ------------------------------ FuncExprNode ---------------------------------
1034 
1035 void FuncExprNode::addParams()
1036 {
1037  for (ParameterNode *p = param.get(); p != nullptr; p = p->nextParam()) {
1038  body->addParam(p->ident());
1039  }
1040 }
1041 
1042 void FuncExprNode::recurseVisit(NodeVisitor *visitor)
1043 {
1044  recurseVisitLink(visitor, param);
1045  recurseVisitLink(visitor, body);
1046 }
1047 
1048 // ------------------------------ SourceElementsNode ---------------------------
1049 
1050 SourceElementsNode::SourceElementsNode(StatementNode *s1)
1051  : node(s1), next(this)
1052 {
1053  Parser::noteNodeCycle(this);
1054  setLoc(s1->firstLine(), s1->lastLine());
1055 }
1056 
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 
1064 void SourceElementsNode::breakCycle()
1065 {
1066  next = nullptr;
1067 }
1068 
1069 void SourceElementsNode::recurseVisit(NodeVisitor *visitor)
1070 {
1071  recurseVisitLink(visitor, node);
1072  recurseVisitLink(visitor, next);
1073 }
1074 
1075 // ------------------------------ ProgramNode ----------------------------------
1076 
1077 ProgramNode::ProgramNode(SourceElementsNode *s) : FunctionBodyNode(s)
1078 {
1079 }
1080 
1081 // ------------------------------ PackageNameNode ------------------------------
1082 void PackageNameNode::recurseVisit(NodeVisitor *visitor)
1083 {
1084  recurseVisitLink(visitor, names);
1085 }
1086 
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 
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 
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 
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 
1195 void ImportStatement::recurseVisit(NodeVisitor *visitor)
1196 {
1197  recurseVisitLink(visitor, name);
1198 }
1199 
1200 } //namespace KJS
QCA_EXPORT void init()
char * toString(const T &value)
QString label(StandardShortcut id)
QString name(StandardShortcut id)
const QList< QKeySequence > & next()
static const List & empty()
Returns a pointer to a static instance of an empty list.
Definition: list.cpp:311
QString message
const QList< QKeySequence > & end()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Mar 26 2023 03:56:21 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.