Commit a89639e7 authored by jgruber's avatar jgruber Committed by Commit bot

Handle unicode correctly in CallPrinter

CallPrinter currently has only a single use, namely to print the call
site when throwing CalledNonCallable (ConstructedNonConstructable)
errors. This ensures that unicode call sites such as "あいう"() are
printed correctly by using an IncrementalStringBuilder internally.

BUG=637167

Review-Url: https://codereview.chromium.org/2265073002
Cr-Commit-Position: refs/heads/master@{#38790}
parent 2e6db3af
...@@ -13,27 +13,22 @@ ...@@ -13,27 +13,22 @@
namespace v8 { namespace v8 {
namespace internal { namespace internal {
CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin) { CallPrinter::CallPrinter(Isolate* isolate, bool is_builtin)
: builder_(isolate) {
isolate_ = isolate; isolate_ = isolate;
output_ = NULL;
size_ = 0;
pos_ = 0;
position_ = 0; position_ = 0;
num_prints_ = 0;
found_ = false; found_ = false;
done_ = false; done_ = false;
is_builtin_ = is_builtin; is_builtin_ = is_builtin;
InitializeAstVisitor(isolate); InitializeAstVisitor(isolate);
} }
Handle<String> CallPrinter::Print(FunctionLiteral* program, int position) {
CallPrinter::~CallPrinter() { DeleteArray(output_); } num_prints_ = 0;
const char* CallPrinter::Print(FunctionLiteral* program, int position) {
Init();
position_ = position; position_ = position;
Find(program); Find(program);
return output_; return builder_.Finish().ToHandleChecked();
} }
...@@ -41,9 +36,9 @@ void CallPrinter::Find(AstNode* node, bool print) { ...@@ -41,9 +36,9 @@ void CallPrinter::Find(AstNode* node, bool print) {
if (done_) return; if (done_) return;
if (found_) { if (found_) {
if (print) { if (print) {
int start = pos_; int prev_num_prints = num_prints_;
Visit(node); Visit(node);
if (start != pos_) return; if (prev_num_prints != num_prints_) return;
} }
Print("(intermediate value)"); Print("(intermediate value)");
} else { } else {
...@@ -51,45 +46,18 @@ void CallPrinter::Find(AstNode* node, bool print) { ...@@ -51,45 +46,18 @@ void CallPrinter::Find(AstNode* node, bool print) {
} }
} }
void CallPrinter::Print(const char* str) {
void CallPrinter::Init() { if (!found_ || done_) return;
if (size_ == 0) { num_prints_++;
DCHECK(output_ == NULL); builder_.AppendCString(str);
const int initial_size = 256;
output_ = NewArray<char>(initial_size);
size_ = initial_size;
}
output_[0] = '\0';
pos_ = 0;
} }
void CallPrinter::Print(Handle<String> str) {
void CallPrinter::Print(const char* format, ...) {
if (!found_ || done_) return; if (!found_ || done_) return;
for (;;) { num_prints_++;
va_list arguments; builder_.AppendString(str);
va_start(arguments, format);
int n = VSNPrintF(Vector<char>(output_, size_) + pos_, format, arguments);
va_end(arguments);
if (n >= 0) {
// there was enough space - we are done
pos_ += n;
return;
} else {
// there was not enough space - allocate more and try again
const int slack = 32;
int new_size = size_ + (size_ >> 1) + slack;
char* new_output = NewArray<char>(new_size);
MemCopy(new_output, output_, pos_);
DeleteArray(output_);
output_ = new_output;
size_ = new_size;
}
}
} }
void CallPrinter::VisitBlock(Block* node) { void CallPrinter::VisitBlock(Block* node) {
FindStatements(node->statements()); FindStatements(node->statements());
} }
...@@ -236,13 +204,13 @@ void CallPrinter::VisitConditional(Conditional* node) { ...@@ -236,13 +204,13 @@ void CallPrinter::VisitConditional(Conditional* node) {
void CallPrinter::VisitLiteral(Literal* node) { void CallPrinter::VisitLiteral(Literal* node) {
PrintLiteral(*node->value(), true); PrintLiteral(node->value(), true);
} }
void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) { void CallPrinter::VisitRegExpLiteral(RegExpLiteral* node) {
Print("/"); Print("/");
PrintLiteral(*node->pattern(), false); PrintLiteral(node->pattern(), false);
Print("/"); Print("/");
if (node->flags() & RegExp::kGlobal) Print("g"); if (node->flags() & RegExp::kGlobal) Print("g");
if (node->flags() & RegExp::kIgnoreCase) Print("i"); if (node->flags() & RegExp::kIgnoreCase) Print("i");
...@@ -274,7 +242,7 @@ void CallPrinter::VisitVariableProxy(VariableProxy* node) { ...@@ -274,7 +242,7 @@ void CallPrinter::VisitVariableProxy(VariableProxy* node) {
// Variable names of builtins are meaningless due to minification. // Variable names of builtins are meaningless due to minification.
Print("(var)"); Print("(var)");
} else { } else {
PrintLiteral(*node->name(), false); PrintLiteral(node->name(), false);
} }
} }
...@@ -297,7 +265,7 @@ void CallPrinter::VisitProperty(Property* node) { ...@@ -297,7 +265,7 @@ void CallPrinter::VisitProperty(Property* node) {
if (literal != NULL && literal->value()->IsInternalizedString()) { if (literal != NULL && literal->value()->IsInternalizedString()) {
Find(node->obj(), true); Find(node->obj(), true);
Print("."); Print(".");
PrintLiteral(*literal->value(), false); PrintLiteral(literal->value(), false);
} else { } else {
Find(node->obj(), true); Find(node->obj(), true);
Print("["); Print("[");
...@@ -351,7 +319,9 @@ void CallPrinter::VisitUnaryOperation(UnaryOperation* node) { ...@@ -351,7 +319,9 @@ void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
Token::Value op = node->op(); Token::Value op = node->op();
bool needsSpace = bool needsSpace =
op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID; op == Token::DELETE || op == Token::TYPEOF || op == Token::VOID;
Print("(%s%s", Token::String(op), needsSpace ? " " : ""); Print("(");
Print(Token::String(op));
if (needsSpace) Print(" ");
Find(node->expression(), true); Find(node->expression(), true);
Print(")"); Print(")");
} }
...@@ -359,9 +329,9 @@ void CallPrinter::VisitUnaryOperation(UnaryOperation* node) { ...@@ -359,9 +329,9 @@ void CallPrinter::VisitUnaryOperation(UnaryOperation* node) {
void CallPrinter::VisitCountOperation(CountOperation* node) { void CallPrinter::VisitCountOperation(CountOperation* node) {
Print("("); Print("(");
if (node->is_prefix()) Print("%s", Token::String(node->op())); if (node->is_prefix()) Print(Token::String(node->op()));
Find(node->expression(), true); Find(node->expression(), true);
if (node->is_postfix()) Print("%s", Token::String(node->op())); if (node->is_postfix()) Print(Token::String(node->op()));
Print(")"); Print(")");
} }
...@@ -369,7 +339,9 @@ void CallPrinter::VisitCountOperation(CountOperation* node) { ...@@ -369,7 +339,9 @@ void CallPrinter::VisitCountOperation(CountOperation* node) {
void CallPrinter::VisitBinaryOperation(BinaryOperation* node) { void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
Print("("); Print("(");
Find(node->left(), true); Find(node->left(), true);
Print(" %s ", Token::String(node->op())); Print(" ");
Print(Token::String(node->op()));
Print(" ");
Find(node->right(), true); Find(node->right(), true);
Print(")"); Print(")");
} }
...@@ -378,7 +350,9 @@ void CallPrinter::VisitBinaryOperation(BinaryOperation* node) { ...@@ -378,7 +350,9 @@ void CallPrinter::VisitBinaryOperation(BinaryOperation* node) {
void CallPrinter::VisitCompareOperation(CompareOperation* node) { void CallPrinter::VisitCompareOperation(CompareOperation* node) {
Print("("); Print("(");
Find(node->left(), true); Find(node->left(), true);
Print(" %s ", Token::String(node->op())); Print(" ");
Print(Token::String(node->op()));
Print(" ");
Find(node->right(), true); Find(node->right(), true);
Print(")"); Print(")");
} }
...@@ -427,32 +401,30 @@ void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) { ...@@ -427,32 +401,30 @@ void CallPrinter::FindArguments(ZoneList<Expression*>* arguments) {
} }
} }
void CallPrinter::PrintLiteral(Handle<Object> value, bool quote) {
void CallPrinter::PrintLiteral(Object* value, bool quote) { if (value->IsString()) {
Object* object = value;
if (object->IsString()) {
if (quote) Print("\""); if (quote) Print("\"");
Print("%s", String::cast(object)->ToCString().get()); Print(Handle<String>::cast(value));
if (quote) Print("\""); if (quote) Print("\"");
} else if (object->IsNull(isolate_)) { } else if (value->IsNull(isolate_)) {
Print("null"); Print("null");
} else if (object->IsTrue(isolate_)) { } else if (value->IsTrue(isolate_)) {
Print("true"); Print("true");
} else if (object->IsFalse(isolate_)) { } else if (value->IsFalse(isolate_)) {
Print("false"); Print("false");
} else if (object->IsUndefined(isolate_)) { } else if (value->IsUndefined(isolate_)) {
Print("undefined"); Print("undefined");
} else if (object->IsNumber()) { } else if (value->IsNumber()) {
Print("%g", object->Number()); Print(isolate_->factory()->NumberToString(value));
} else if (object->IsSymbol()) { } else if (value->IsSymbol()) {
// Symbols can only occur as literals if they were inserted by the parser. // Symbols can only occur as literals if they were inserted by the parser.
PrintLiteral(Symbol::cast(object)->name(), false); PrintLiteral(handle(Handle<Symbol>::cast(value)->name(), isolate_), false);
} }
} }
void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) { void CallPrinter::PrintLiteral(const AstRawString* value, bool quote) {
PrintLiteral(*value->string(), quote); PrintLiteral(value->string(), quote);
} }
......
...@@ -8,6 +8,7 @@ ...@@ -8,6 +8,7 @@
#include "src/allocation.h" #include "src/allocation.h"
#include "src/ast/ast.h" #include "src/ast/ast.h"
#include "src/base/compiler-specific.h" #include "src/base/compiler-specific.h"
#include "src/string-builder.h"
namespace v8 { namespace v8 {
namespace internal { namespace internal {
...@@ -15,15 +16,10 @@ namespace internal { ...@@ -15,15 +16,10 @@ namespace internal {
class CallPrinter final : public AstVisitor<CallPrinter> { class CallPrinter final : public AstVisitor<CallPrinter> {
public: public:
explicit CallPrinter(Isolate* isolate, bool is_builtin); explicit CallPrinter(Isolate* isolate, bool is_builtin);
~CallPrinter();
// The following routine prints the node with position |position| into a // The following routine prints the node with position |position| into a
// string. The result string is alive as long as the CallPrinter is alive. // string.
const char* Print(FunctionLiteral* program, int position); Handle<String> Print(FunctionLiteral* program, int position);
void PRINTF_FORMAT(2, 3) Print(const char* format, ...);
void Find(AstNode* node, bool print = false);
// Individual nodes // Individual nodes
#define DECLARE_VISIT(type) void Visit##type(type* node); #define DECLARE_VISIT(type) void Visit##type(type* node);
...@@ -31,11 +27,14 @@ class CallPrinter final : public AstVisitor<CallPrinter> { ...@@ -31,11 +27,14 @@ class CallPrinter final : public AstVisitor<CallPrinter> {
#undef DECLARE_VISIT #undef DECLARE_VISIT
private: private:
void Init(); void Print(const char* str);
void Print(Handle<String> str);
void Find(AstNode* node, bool print = false);
Isolate* isolate_; Isolate* isolate_;
char* output_; // output string buffer int num_prints_;
int size_; // output_ size IncrementalStringBuilder builder_;
int pos_; // current printing position
int position_; // position of ast node to print int position_; // position of ast node to print
bool found_; bool found_;
bool done_; bool done_;
...@@ -44,7 +43,7 @@ class CallPrinter final : public AstVisitor<CallPrinter> { ...@@ -44,7 +43,7 @@ class CallPrinter final : public AstVisitor<CallPrinter> {
DEFINE_AST_VISITOR_SUBCLASS_MEMBERS(); DEFINE_AST_VISITOR_SUBCLASS_MEMBERS();
protected: protected:
void PrintLiteral(Object* value, bool quote); void PrintLiteral(Handle<Object> value, bool quote);
void PrintLiteral(const AstRawString* value, bool quote); void PrintLiteral(const AstRawString* value, bool quote);
void FindStatements(ZoneList<Statement*>* statements); void FindStatements(ZoneList<Statement*>* statements);
void FindArguments(ZoneList<Expression*>* arguments); void FindArguments(ZoneList<Expression*>* arguments);
......
...@@ -411,10 +411,8 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) { ...@@ -411,10 +411,8 @@ Handle<String> RenderCallSite(Isolate* isolate, Handle<Object> object) {
: new ParseInfo(&zone, location.script())); : new ParseInfo(&zone, location.script()));
if (Parser::ParseStatic(info.get())) { if (Parser::ParseStatic(info.get())) {
CallPrinter printer(isolate, location.function()->shared()->IsBuiltin()); CallPrinter printer(isolate, location.function()->shared()->IsBuiltin());
const char* string = printer.Print(info->literal(), location.start_pos()); Handle<String> str = printer.Print(info->literal(), location.start_pos());
if (strlen(string) > 0) { if (str->length() > 0) return str;
return isolate->factory()->NewStringFromAsciiChecked(string);
}
} else { } else {
isolate->clear_pending_exception(); isolate->clear_pending_exception();
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment