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