source: webkit/trunk/JavaScriptCore/kjs/nodes2string.cpp@ 17306

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

JavaScriptCore:

Reviewed by John.

  • fix iteration of properties of string objects (found because of a warning emitted by the MSVC compiler)
  • kjs/string_object.cpp: (StringInstance::getPropertyNames): Change code that wants to format a number as a string to use UString::from. Before it was using the UString constructor that makes a string from a character!
  • kjs/ustring.h:
  • kjs/ustring.cpp: Remove the dangerous and not all that helpful UString(char) constructor.
  • kjs/grammar.y: Change code to not depend on the UString(char) constructor. This is potentially more efficient anyway because we could overload the + operator some day to handle char* directly instead of creating a UString.
  • kjs/nodes2string.cpp: (SourceStream::operator<<): Change code to not depend on the UString(char) constructor.

LayoutTests:

Reviewed by John.

  • add a test for iteration of properties of string objects
  • fast/js/resources/string-property-iteration.js: Added.
  • fast/js/string-property-iteration-expected.txt: Added.
  • fast/js/string-property-iteration.html: Added.
  • Property svn:eol-style set to native
File size: 14.4 KB
Line 
1/*
2 * This file is part of the KDE libraries
3 * Copyright (C) 2002 Harri Porten ([email protected])
4 * Copyright (C) 2003 Apple Computer, Inc.
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "nodes.h"
25#include "function.h"
26
27namespace KJS {
28 /**
29 * A simple text streaming class that helps with code indentation.
30 */
31 class SourceStream {
32 public:
33 enum Format {
34 Endl, Indent, Unindent
35 };
36
37 UString toString() const { return str; }
38 SourceStream& operator<<(const Identifier &);
39 SourceStream& operator<<(const UString &);
40 SourceStream& operator<<(const char *);
41 SourceStream& operator<<(char);
42 SourceStream& operator<<(Format f);
43 SourceStream& operator<<(const Node *);
44 template <typename T> SourceStream& operator<<(RefPtr<T> n) { return this->operator<<(n.get()); }
45 private:
46 UString str; /* TODO: buffer */
47 UString ind;
48 };
49}
50
51using namespace KJS;
52
53SourceStream& SourceStream::operator<<(char c)
54{
55 UChar ch(c);
56 str += UString(&ch, 1);
57 return *this;
58}
59
60SourceStream& SourceStream::operator<<(const char *s)
61{
62 str += UString(s);
63 return *this;
64}
65
66SourceStream& SourceStream::operator<<(const UString &s)
67{
68 str += s;
69 return *this;
70}
71
72SourceStream& SourceStream::operator<<(const Identifier &s)
73{
74 str += s.ustring();
75 return *this;
76}
77
78SourceStream& SourceStream::operator<<(const Node *n)
79{
80 if (n)
81 n->streamTo(*this);
82 return *this;
83}
84
85SourceStream& SourceStream::operator<<(Format f)
86{
87 switch (f) {
88 case Endl:
89 str += "\n" + ind;
90 break;
91 case Indent:
92 ind += " ";
93 break;
94 case Unindent:
95 ind = ind.substr(0, ind.size() - 2);
96 break;
97 }
98
99 return *this;
100}
101
102UString Node::toString() const
103{
104 SourceStream str;
105 streamTo(str);
106
107 return str.toString();
108}
109
110void NullNode::streamTo(SourceStream &s) const { s << "null"; }
111
112void BooleanNode::streamTo(SourceStream &s) const
113{
114 s << (value ? "true" : "false");
115}
116
117void NumberNode::streamTo(SourceStream &s) const { s << UString::from(value); }
118
119void StringNode::streamTo(SourceStream &s) const
120{
121 s << '"' << escapeStringForPrettyPrinting(value) << '"';
122}
123
124void RegExpNode::streamTo(SourceStream &s) const
125{
126 s << "/" << pattern << "/" << flags;
127}
128
129void ThisNode::streamTo(SourceStream &s) const { s << "this"; }
130
131void ResolveNode::streamTo(SourceStream &s) const { s << ident; }
132
133void GroupNode::streamTo(SourceStream &s) const
134{
135 s << "(" << group << ")";
136}
137
138void ElementNode::streamTo(SourceStream &s) const
139{
140 for (const ElementNode *n = this; n; n = n->next.get()) {
141 for (int i = 0; i < n->elision; i++)
142 s << ",";
143 s << n->node;
144 }
145}
146
147void ArrayNode::streamTo(SourceStream &s) const
148{
149 s << "[" << element;
150 for (int i = 0; i < elision; i++)
151 s << ",";
152 s << "]";
153}
154
155void ObjectLiteralNode::streamTo(SourceStream &s) const
156{
157 if (list)
158 s << "{ " << list << " }";
159 else
160 s << "{ }";
161}
162
163void PropertyListNode::streamTo(SourceStream &s) const
164{
165 s << node;
166
167 for (const PropertyListNode *n = next.get(); n; n = n->next.get())
168 s << ", " << n->node;
169}
170
171void PropertyNode::streamTo(SourceStream &s) const
172{
173 switch (type) {
174 case Constant:
175 s << name << ": " << assign;
176 break;
177 case Getter:
178 case Setter: {
179 const FuncExprNode *func = static_cast<const FuncExprNode *>(assign.get());
180 if (type == Getter)
181 s << "get ";
182 else
183 s << "set ";
184
185 s << name << "(" << func->param << ")" << func->body;
186 break;
187 }
188 }
189}
190
191void PropertyNameNode::streamTo(SourceStream &s) const
192{
193 if (str.isNull())
194 s << UString::from(numeric);
195 else
196 s << str;
197}
198
199void BracketAccessorNode::streamTo(SourceStream &s) const
200{
201 s << expr1 << "[" << expr2 << "]";
202}
203
204void DotAccessorNode::streamTo(SourceStream &s) const
205{
206 s << expr << "." << ident;
207}
208
209void ArgumentListNode::streamTo(SourceStream &s) const
210{
211 s << expr;
212 for (ArgumentListNode *n = next.get(); n; n = n->next.get())
213 s << ", " << n->expr;
214}
215
216void ArgumentsNode::streamTo(SourceStream &s) const
217{
218 s << "(" << list << ")";
219}
220
221void NewExprNode::streamTo(SourceStream &s) const
222{
223 s << "new " << expr << args;
224}
225
226void FunctionCallValueNode::streamTo(SourceStream &s) const
227{
228 s << expr << args;
229}
230
231void FunctionCallResolveNode::streamTo(SourceStream &s) const
232{
233 s << ident << args;
234}
235
236void FunctionCallBracketNode::streamTo(SourceStream &s) const
237{
238 s << base << "[" << subscript << "]" << args;
239}
240
241void FunctionCallParenBracketNode::streamTo(SourceStream &s) const
242{
243 s << "(" << base << "[" << subscript << "])" << args;
244}
245
246void FunctionCallDotNode::streamTo(SourceStream &s) const
247{
248 s << base << "." << ident << args;
249}
250
251void FunctionCallParenDotNode::streamTo(SourceStream &s) const
252{
253 s << "(" << base << "." << ident << ")" << args;
254}
255
256void PostfixResolveNode::streamTo(SourceStream &s) const
257{
258 s << m_ident;
259 if (m_oper == OpPlusPlus)
260 s << "++";
261 else
262 s << "--";
263}
264
265void PostfixBracketNode::streamTo(SourceStream &s) const
266{
267 s << m_base << "[" << m_subscript << "]";
268 if (m_oper == OpPlusPlus)
269 s << "++";
270 else
271 s << "--";
272}
273
274void PostfixDotNode::streamTo(SourceStream &s) const
275{
276 s << m_base << "." << m_ident;
277 if (m_oper == OpPlusPlus)
278 s << "++";
279 else
280 s << "--";
281}
282
283void DeleteResolveNode::streamTo(SourceStream &s) const
284{
285 s << "delete " << m_ident;
286}
287
288void DeleteBracketNode::streamTo(SourceStream &s) const
289{
290 s << "delete " << m_base << "[" << m_subscript << "]";
291}
292
293void DeleteDotNode::streamTo(SourceStream &s) const
294{
295 s << "delete " << m_base << "." << m_ident;
296}
297
298void DeleteValueNode::streamTo(SourceStream &s) const
299{
300 s << "delete " << m_expr;
301}
302
303void VoidNode::streamTo(SourceStream &s) const
304{
305 s << "void " << expr;
306}
307
308void TypeOfValueNode::streamTo(SourceStream &s) const
309{
310 s << "typeof " << m_expr;
311}
312
313void TypeOfResolveNode::streamTo(SourceStream &s) const
314{
315 s << "typeof " << m_ident;
316}
317
318void PrefixResolveNode::streamTo(SourceStream &s) const
319{
320 if (m_oper == OpPlusPlus)
321 s << "++";
322 else
323 s << "--";
324 s << m_ident;
325}
326
327void PrefixBracketNode::streamTo(SourceStream &s) const
328{
329 if (m_oper == OpPlusPlus)
330 s << "++";
331 else
332 s << "--";
333 s << m_base << "[" << m_subscript << "]";
334}
335
336void PrefixDotNode::streamTo(SourceStream &s) const
337{
338 if (m_oper == OpPlusPlus)
339 s << "++";
340 else
341 s << "--";
342 s << m_base << "." << m_ident;
343}
344
345void UnaryPlusNode::streamTo(SourceStream &s) const
346{
347 s << "+" << expr;
348}
349
350void NegateNode::streamTo(SourceStream &s) const
351{
352 s << "-" << expr;
353}
354
355void BitwiseNotNode::streamTo(SourceStream &s) const
356{
357 s << "~" << expr;
358}
359
360void LogicalNotNode::streamTo(SourceStream &s) const
361{
362 s << "!" << expr;
363}
364
365void MultNode::streamTo(SourceStream &s) const
366{
367 s << term1 << oper << term2;
368}
369
370void AddNode::streamTo(SourceStream &s) const
371{
372 s << term1 << oper << term2;
373}
374
375void ShiftNode::streamTo(SourceStream &s) const
376{
377 s << term1;
378 if (oper == OpLShift)
379 s << "<<";
380 else if (oper == OpRShift)
381 s << ">>";
382 else
383 s << ">>>";
384 s << term2;
385}
386
387void RelationalNode::streamTo(SourceStream &s) const
388{
389 s << expr1;
390 switch (oper) {
391 case OpLess:
392 s << " < ";
393 break;
394 case OpGreater:
395 s << " > ";
396 break;
397 case OpLessEq:
398 s << " <= ";
399 break;
400 case OpGreaterEq:
401 s << " >= ";
402 break;
403 case OpInstanceOf:
404 s << " instanceof ";
405 break;
406 case OpIn:
407 s << " in ";
408 break;
409 default:
410 ;
411 }
412 s << expr2;
413}
414
415void EqualNode::streamTo(SourceStream &s) const
416{
417 s << expr1;
418 switch (oper) {
419 case OpEqEq:
420 s << " == ";
421 break;
422 case OpNotEq:
423 s << " != ";
424 break;
425 case OpStrEq:
426 s << " === ";
427 break;
428 case OpStrNEq:
429 s << " !== ";
430 break;
431 default:
432 ;
433 }
434 s << expr2;
435}
436
437void BitOperNode::streamTo(SourceStream &s) const
438{
439 s << expr1;
440 if (oper == OpBitAnd)
441 s << " & ";
442 else if (oper == OpBitXOr)
443 s << " ^ ";
444 else
445 s << " | ";
446 s << expr2;
447}
448
449void BinaryLogicalNode::streamTo(SourceStream &s) const
450{
451 s << expr1 << (oper == OpAnd ? " && " : " || ") << expr2;
452}
453
454void ConditionalNode::streamTo(SourceStream &s) const
455{
456 s << logical << " ? " << expr1 << " : " << expr2;
457}
458
459static void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
460{
461 const char *opStr;
462 switch (oper) {
463 case OpEqual:
464 opStr = " = ";
465 break;
466 case OpMultEq:
467 opStr = " *= ";
468 break;
469 case OpDivEq:
470 opStr = " /= ";
471 break;
472 case OpPlusEq:
473 opStr = " += ";
474 break;
475 case OpMinusEq:
476 opStr = " -= ";
477 break;
478 case OpLShift:
479 opStr = " <<= ";
480 break;
481 case OpRShift:
482 opStr = " >>= ";
483 break;
484 case OpURShift:
485 opStr = " >>>= ";
486 break;
487 case OpAndEq:
488 opStr = " &= ";
489 break;
490 case OpXOrEq:
491 opStr = " ^= ";
492 break;
493 case OpOrEq:
494 opStr = " |= ";
495 break;
496 case OpModEq:
497 opStr = " %= ";
498 break;
499 default:
500 opStr = " ?= ";
501 }
502 s << opStr;
503}
504
505void AssignResolveNode::streamTo(SourceStream &s) const
506{
507 s << m_ident;
508 streamAssignmentOperatorTo(s, m_oper);
509 s << m_right;
510}
511
512void AssignBracketNode::streamTo(SourceStream &s) const
513{
514 s << m_base << "[" << m_subscript << "]";
515 streamAssignmentOperatorTo(s, m_oper);
516 s << m_right;
517}
518
519void AssignDotNode::streamTo(SourceStream &s) const
520{
521 s << m_base << "." << m_ident;
522 streamAssignmentOperatorTo(s, m_oper);
523 s << m_right;
524}
525
526void CommaNode::streamTo(SourceStream &s) const
527{
528 s << expr1 << ", " << expr2;
529}
530
531void AssignExprNode::streamTo(SourceStream &s) const
532{
533 s << " = " << expr;
534}
535
536void VarDeclNode::streamTo(SourceStream &s) const
537{
538 s << ident << init;
539}
540
541void VarDeclListNode::streamTo(SourceStream &s) const
542{
543 s << var;
544 for (VarDeclListNode *n = next.get(); n; n = n->next.get())
545 s << ", " << n->var;
546}
547
548void VarStatementNode::streamTo(SourceStream &s) const
549{
550 s << SourceStream::Endl << "var " << next << ";";
551}
552
553void BlockNode::streamTo(SourceStream &s) const
554{
555 s << SourceStream::Endl << "{" << SourceStream::Indent
556 << source << SourceStream::Unindent << SourceStream::Endl << "}";
557}
558
559void EmptyStatementNode::streamTo(SourceStream &s) const
560{
561 s << SourceStream::Endl << ";";
562}
563
564void ExprStatementNode::streamTo(SourceStream &s) const
565{
566 s << SourceStream::Endl << expr << ";";
567}
568
569void IfNode::streamTo(SourceStream &s) const
570{
571 s << SourceStream::Endl << "if (" << expr << ")" << SourceStream::Indent
572 << statement1 << SourceStream::Unindent;
573 if (statement2)
574 s << SourceStream::Endl << "else" << SourceStream::Indent
575 << statement2 << SourceStream::Unindent;
576}
577
578void DoWhileNode::streamTo(SourceStream &s) const
579{
580 s << SourceStream::Endl << "do " << SourceStream::Indent
581 << statement << SourceStream::Unindent << SourceStream::Endl
582 << "while (" << expr << ");";
583}
584
585void WhileNode::streamTo(SourceStream &s) const
586{
587 s << SourceStream::Endl << "while (" << expr << ")" << SourceStream::Indent
588 << statement << SourceStream::Unindent;
589}
590
591void ForNode::streamTo(SourceStream &s) const
592{
593 s << SourceStream::Endl << "for ("
594 << expr1 // TODO: doesn't properly do "var i = 0"
595 << "; " << expr2
596 << "; " << expr3
597 << ")" << SourceStream::Indent << statement << SourceStream::Unindent;
598}
599
600void ForInNode::streamTo(SourceStream &s) const
601{
602 s << SourceStream::Endl << "for (";
603 if (varDecl)
604 s << "var " << varDecl;
605 else
606 s << lexpr;
607
608 if (init)
609 s << " = " << init;
610 s << " in " << expr << ")" << SourceStream::Indent
611 << statement << SourceStream::Unindent;
612}
613
614void ContinueNode::streamTo(SourceStream &s) const
615{
616 s << SourceStream::Endl << "continue";
617 if (!ident.isNull())
618 s << " " << ident;
619 s << ";";
620}
621
622void BreakNode::streamTo(SourceStream &s) const
623{
624 s << SourceStream::Endl << "break";
625 if (!ident.isNull())
626 s << " " << ident;
627 s << ";";
628}
629
630void ReturnNode::streamTo(SourceStream &s) const
631{
632 s << SourceStream::Endl << "return";
633 if (value)
634 s << " " << value;
635 s << ";";
636}
637
638void WithNode::streamTo(SourceStream &s) const
639{
640 s << SourceStream::Endl << "with (" << expr << ") "
641 << statement;
642}
643
644void CaseClauseNode::streamTo(SourceStream &s) const
645{
646 s << SourceStream::Endl;
647 if (expr)
648 s << "case " << expr;
649 else
650 s << "default";
651 s << ":" << SourceStream::Indent;
652 if (source)
653 s << source;
654 s << SourceStream::Unindent;
655}
656
657void ClauseListNode::streamTo(SourceStream &s) const
658{
659 for (const ClauseListNode *n = this; n; n = n->getNext())
660 s << n->getClause();
661}
662
663void CaseBlockNode::streamTo(SourceStream &s) const
664{
665 for (const ClauseListNode *n = list1.get(); n; n = n->getNext())
666 s << n->getClause();
667 if (def)
668 s << def;
669 for (const ClauseListNode *n = list2.get(); n; n = n->getNext())
670 s << n->getClause();
671}
672
673void SwitchNode::streamTo(SourceStream &s) const
674{
675 s << SourceStream::Endl << "switch (" << expr << ") {"
676 << SourceStream::Indent << block << SourceStream::Unindent
677 << SourceStream::Endl << "}";
678}
679
680void LabelNode::streamTo(SourceStream &s) const
681{
682 s << SourceStream::Endl << label << ":" << SourceStream::Indent
683 << statement << SourceStream::Unindent;
684}
685
686void ThrowNode::streamTo(SourceStream &s) const
687{
688 s << SourceStream::Endl << "throw " << expr << ";";
689}
690
691void TryNode::streamTo(SourceStream &s) const
692{
693 s << "try " << tryBlock;
694 if (catchBlock)
695 s << SourceStream::Endl << "catch (" << exceptionIdent << ")" << catchBlock;
696 if (finallyBlock)
697 s << SourceStream::Endl << "finally " << finallyBlock;
698}
699
700void ParameterNode::streamTo(SourceStream &s) const
701{
702 s << id;
703 for (ParameterNode *n = next.get(); n; n = n->next.get())
704 s << ", " << n->id;
705}
706
707void FuncDeclNode::streamTo(SourceStream &s) const
708{
709 s << SourceStream::Endl << "function " << ident << "(" << param << ")" << body;
710}
711
712void FuncExprNode::streamTo(SourceStream &s) const
713{
714 s << "function " << ident << "(" << param << ")" << body;
715}
716
717void SourceElementsNode::streamTo(SourceStream &s) const
718{
719 for (const SourceElementsNode *n = this; n; n = n->next.get())
720 s << n->node;
721}
Note: See TracBrowser for help on using the repository browser.