29 #include "scriptfunction.h"
34 #if defined(WTF_COMPILER_CWP)
35 #pragma auto_inline off
36 #elif defined(WTF_COMPILER_MSVC)
37 #pragma auto_inline(off)
38 #elif defined(WTF_COMPILER_GCC)
52 const bool kDontQuote =
false, kQuote =
true;
61 enum eIndent { Indent };
62 enum eUnindent { Unindent };
64 static const int kBufSize = 2048;
65 typedef unsigned short UTF16;
66 SourceStream() : indent(0), bufUsed(0), reindentLine(0), reindenting(false) {}
74 SourceStream &
operator<<(
const char *s) NOINLINE;
77 SourceStream &
operator<<(
const Node *n) NOINLINE;
78 SourceStream &
operator<<(
const StatementNode *n) NOINLINE;
79 SourceStream &
operator<<(Operator op) NOINLINE;
90 SourceStream &append(
const Node *expr1,
const char *sep,
const Node *expr2) NOINLINE;
91 SourceStream &append(
const RefPtr<Node> &expr1,
const char *sep,
const RefPtr<Node> &expr2) NOINLINE;
92 SourceStream &append(
const UTF16 *src,
int srcLen) NOINLINE;
93 SourceStream &append(
const UString &inStr,
bool quote) NOINLINE;
95 inline SourceStream &
operator<<(
const RefPtr<T> &n)
100 void setReindenting(
int baseLine)
103 reindentLine = baseLine;
109 UTF16 buffer[kBufSize];
110 void flush() NOINLINE;
113 buffer[bufUsed++] = ch;
117 buffer[bufUsed++] =
static_cast<unsigned char>(ch);
127 SourceStream &SourceStream::operator<<(Operator op)
129 assert(op == OpPlusPlus || op == OpMinusMinus);
130 return *
this << ((op == OpPlusPlus) ?
"++" :
"--");
133 void SourceStream::flush()
136 str.append(
UString(
reinterpret_cast<const UChar *
>(buffer), bufUsed));
141 SourceStream &SourceStream::operator<<(
char c)
143 if (bufUsed == kBufSize) {
150 SourceStream &SourceStream::operator<<(
const char *s)
152 assert(strlen(s) < 100);
153 if (bufUsed > kBufSize - 100) {
160 for (UTF16 *dst = &buffer[i] - 1; (ch = *++s) != 0; ++i) {
168 SourceStream &SourceStream::operator<<(
const UString &s)
170 return append(&s.
data()->uc, s.
size());
173 SourceStream &SourceStream::operator<<(
const Identifier &s)
175 return append(s.
ustring(), kDontQuote);
178 SourceStream &SourceStream::operator<<(
const StatementNode *n)
184 int firstLine = reindentLine + 1;
187 n->setLoc(firstLine, reindentLine - 1);
193 SourceStream &SourceStream::operator<<(
const Node *n)
201 SourceStream &SourceStream::operator<<(eEndl)
203 if (bufUsed > kBufSize - 1 - indent) {
210 UTF16 *dst = &buffer[bufUsed];
211 for (
int i = indent; i > 0; --i) {
220 SourceStream &SourceStream::append(
const Node *expr1,
const char *sep,
const Node *expr2)
222 return *
this << expr1 << sep << expr2;
226 SourceStream::append(
const RefPtr<Node> &expr1,
const char *sep,
const RefPtr<Node> &expr2)
228 return *
this << expr1 << sep << expr2;
231 SourceStream &SourceStream::append(
const UTF16 *src,
int srcLen)
233 if (kBufSize - bufUsed < srcLen) {
236 if (kBufSize - bufUsed < srcLen) {
237 str.append(
UString(
reinterpret_cast<const UChar *
>(src), srcLen));
239 UTF16 *dst = &buffer[bufUsed];
242 while (srcLen-- > 0) {
251 SourceStream &SourceStream::append(
const UString &inStr,
bool quote)
256 const UTF16 *src = &inStr.
data()->uc;
257 const size_t size = inStr.
size();
258 for (
size_t i = 0; i < size; ++i) {
259 if (bufUsed >= kBufSize - 8) {
262 UTF16 c = *src++, esc =
'\\';
265 case '\n': c =
'n';
break;
266 case '\r': c =
'r';
break;
267 case '\t': c =
't';
break;
270 if (c >= 128 || !isprint(c)) {
272 int len = sprintf(hexValue, (c < 256) ?
"\\x%02X" :
"\\u%04X", c);
273 UTF16 *dst = &buffer[bufUsed];
275 for (
int j = 0; j < len; ++j) {
276 dst[j] = hexValue[j];
295 UString FunctionImp::toSource()
const
299 str.append(functionName().ustring(), kDontQuote) <<
'(';
301 const int numParams = body->numParams();
302 for (
int i = 0; i < numParams; ++i) {
306 str << body->paramName(i).
ustring();
311 return str.toString();
319 return str.toString();
322 UString Node::reindent(
int baseLine)
const
325 str.setReindenting(baseLine);
329 return str.toString();
332 void NullNode::streamTo(SourceStream &s)
const
337 void BooleanNode::streamTo(SourceStream &s)
const
339 s << (value() ?
"true" :
"false");
342 void NumberNode::streamTo(SourceStream &s)
const
347 void StringNode::streamTo(SourceStream &s)
const
349 s.append(value(), kQuote);
352 void RegExpNode::streamTo(SourceStream &s)
const
354 s <<
'/' <<
pattern <<
'/' << flags;
357 void ThisNode::streamTo(SourceStream &s)
const
362 void VarAccessNode::streamTo(SourceStream &s)
const
367 void GroupNode::streamTo(SourceStream &s)
const
369 s <<
'(' << group <<
')';
372 void ElementNode::streamTo(SourceStream &s)
const
374 for (
const ElementNode *n =
this; n; n = n->next.get()) {
375 for (
int i = 0; i < n->elision; i++) {
385 void ArrayNode::streamTo(SourceStream &s)
const
388 for (
int i = 0; i < elision; i++) {
393 if (opt && element) {
399 void ObjectLiteralNode::streamTo(SourceStream &s)
const
402 s <<
"{ " <<
list <<
" }";
408 void PropertyListNode::streamTo(SourceStream &s)
const
412 for (
const PropertyListNode *n =
next.get(); n; n = n->next.get()) {
413 s <<
", " << n->node;
417 void PropertyNode::streamTo(SourceStream &s)
const
421 s <<
name <<
": " << assign;
425 const FuncExprNode *func =
static_cast<const FuncExprNode *
>(assign.get());
426 if (type == Getter) {
432 s <<
name <<
'(' << func->param <<
')' << func->body;
438 void PropertyNameNode::streamTo(SourceStream &s)
const
440 s.append(str.ustring(), kQuote);
443 void BracketAccessorNode::streamTo(SourceStream &s)
const
445 s.append(expr1,
"[", expr2) <<
']';
448 void DotAccessorNode::streamTo(SourceStream &s)
const
450 s << expr <<
'.' << ident;
453 void ArgumentListNode::streamTo(SourceStream &s)
const
456 for (ArgumentListNode *n =
next.get(); n; n = n->next.get()) {
457 s <<
", " << n->expr;
461 void ArgumentsNode::streamTo(SourceStream &s)
const
463 s <<
'(' <<
list <<
')';
466 void NewExprNode::streamTo(SourceStream &s)
const
468 s <<
"new " << expr << args;
471 void FunctionCallValueNode::streamTo(SourceStream &s)
const
476 void FunctionCallReferenceNode::streamTo(SourceStream &s)
const
481 void PostfixNode::streamTo(SourceStream &s)
const
483 s << m_loc << m_oper;
486 void DeleteReferenceNode::streamTo(SourceStream &s)
const
488 s <<
"delete " << loc;
491 void DeleteValueNode::streamTo(SourceStream &s)
const
493 s <<
"delete " << m_expr;
496 void VoidNode::streamTo(SourceStream &s)
const
498 s <<
"void " << expr;
501 void TypeOfValueNode::streamTo(SourceStream &s)
const
503 s <<
"typeof " << m_expr;
506 void TypeOfVarNode::streamTo(SourceStream &s)
const
508 s <<
"typeof " << loc;
511 void PrefixNode::streamTo(SourceStream &s)
const
513 s << m_oper << m_loc;
516 void UnaryPlusNode::streamTo(SourceStream &s)
const
521 void NegateNode::streamTo(SourceStream &s)
const
526 void BitwiseNotNode::streamTo(SourceStream &s)
const
531 void LogicalNotNode::streamTo(SourceStream &s)
const
536 void BinaryOperatorNode::streamTo(SourceStream &s)
const
580 opStr =
" instanceof ";
604 assert(!
"Unhandled case in BinaryOperatorNode::streamTo()");
608 s.append(expr1, opStr, expr2);
611 void BinaryLogicalNode::streamTo(SourceStream &s)
const
613 s.append(expr1, (oper == OpAnd ?
" && " :
" || "), expr2);
616 void ConditionalNode::streamTo(SourceStream &s)
const
618 s << logical <<
" ? ";
619 s.append(expr1,
" : ", expr2);
622 static void streamAssignmentOperatorTo(SourceStream &s, Operator oper)
668 void AssignNode::streamTo(SourceStream &s)
const
671 streamAssignmentOperatorTo(s, m_oper);
676 void CommaNode::streamTo(SourceStream &s)
const
678 s.append(expr1,
", ", expr2);
681 void AssignExprNode::streamTo(SourceStream &s)
const
686 void VarDeclNode::streamTo(SourceStream &s)
const
691 void VarDeclListNode::streamTo(SourceStream &s)
const
694 for (VarDeclListNode *n =
next.get(); n; n = n->next.get()) {
699 void VarStatementNode::streamTo(SourceStream &s)
const
701 s << SourceStream::Endl <<
next <<
';';
704 void BlockNode::streamTo(SourceStream &s)
const
706 s << SourceStream::Endl <<
'{' << SourceStream::Indent
707 << source << SourceStream::Unindent << SourceStream::Endl <<
'}';
710 void ProgramNode::streamTo(SourceStream &s)
const
713 s << source << SourceStream::Endl;
716 void EmptyStatementNode::streamTo(SourceStream &s)
const
718 s << SourceStream::Endl <<
';';
721 void ExprStatementNode::streamTo(SourceStream &s)
const
723 s << SourceStream::Endl << expr <<
';';
726 void IfNode::streamTo(SourceStream &s)
const
728 s << SourceStream::Endl <<
"if (" << expr <<
')' << SourceStream::Indent
729 << statement1 << SourceStream::Unindent;
731 s << SourceStream::Endl <<
"else" << SourceStream::Indent
732 << statement2 << SourceStream::Unindent;
735 void DoWhileNode::streamTo(SourceStream &s)
const
737 s << SourceStream::Endl <<
"do " << SourceStream::Indent
738 << statement << SourceStream::Unindent << SourceStream::Endl
739 <<
"while (" << expr <<
");";
742 void WhileNode::streamTo(SourceStream &s)
const
744 s << SourceStream::Endl <<
"while (" << expr <<
')' << SourceStream::Indent
745 << statement << SourceStream::Unindent;
748 void ForNode::streamTo(SourceStream &s)
const
750 s << SourceStream::Endl <<
"for ("
754 <<
')' << SourceStream::Indent << statement << SourceStream::Unindent;
757 void ForInNode::streamTo(SourceStream &s)
const
759 s << SourceStream::Endl <<
"for (";
761 s <<
"var " << varDecl;
766 s <<
" in " << expr <<
')' << SourceStream::Indent
767 << statement << SourceStream::Unindent;
770 void ContinueNode::streamTo(SourceStream &s)
const
772 s << SourceStream::Endl <<
"continue";
773 if (!ident.isNull()) {
779 void BreakNode::streamTo(SourceStream &s)
const
781 s << SourceStream::Endl <<
"break";
782 if (!ident.isNull()) {
788 void ReturnNode::streamTo(SourceStream &s)
const
790 s << SourceStream::Endl <<
"return";
797 void WithNode::streamTo(SourceStream &s)
const
799 s << SourceStream::Endl <<
"with (" << expr <<
") "
803 void CaseClauseNode::streamTo(SourceStream &s)
const
805 s << SourceStream::Endl;
807 s <<
"case " << expr;
811 s <<
':' << SourceStream::Indent;
815 s << SourceStream::Unindent;
818 void ClauseListNode::streamTo(SourceStream &s)
const
820 for (
const ClauseListNode *n =
this; n; n = n->getNext()) {
825 void CaseBlockNode::streamTo(SourceStream &s)
const
827 for (
const ClauseListNode *n = list1.get(); n; n = n->getNext()) {
833 for (
const ClauseListNode *n = list2.get(); n; n = n->getNext()) {
838 void SwitchNode::streamTo(SourceStream &s)
const
840 s << SourceStream::Endl <<
"switch (" << expr <<
") {"
841 << SourceStream::Indent << block << SourceStream::Unindent
842 << SourceStream::Endl <<
'}';
845 void LabelNode::streamTo(SourceStream &s)
const
847 s << SourceStream::Endl <<
label <<
':' << SourceStream::Indent
848 << statement << SourceStream::Unindent;
851 void ThrowNode::streamTo(SourceStream &s)
const
853 s << SourceStream::Endl <<
"throw " << expr <<
';';
856 void TryNode::streamTo(SourceStream &s)
const
858 s << SourceStream::Endl <<
"try " << tryBlock;
860 s << SourceStream::Endl <<
"catch (" << exceptionIdent <<
')' << catchBlock;
863 s << SourceStream::Endl <<
"finally " << finallyBlock;
867 void ParameterNode::streamTo(SourceStream &s)
const
870 for (ParameterNode *n =
next.get(); n; n = n->next.get()) {
875 void FuncDeclNode::streamTo(SourceStream &s)
const
877 s << SourceStream::Endl <<
"function " << ident <<
'(' << param <<
')' << body;
880 void FuncExprNode::streamTo(SourceStream &s)
const
882 s <<
"function " << ident <<
'(' << param <<
')' << body;
885 void SourceElementsNode::streamTo(SourceStream &s)
const
887 for (
const SourceElementsNode *n =
this; n; n = n->next.get()) {
892 void PackageNameNode::streamTo(SourceStream &s)
const
900 void ImportStatement::streamTo(SourceStream &s)
const
902 s << SourceStream::Endl <<
"import ";
906 s <<
name << (wld ?
".*;" :
";");