Handle "//# sourceURL" comments in the Parser instead of the JS.
BUG=v8:2948 LOG=N R=svenpanne@chromium.org, yurys@chromium.org Review URL: https://codereview.chromium.org/316173002 git-svn-id: https://v8.googlecode.com/svn/branches/bleeding_edge@22137 ce2b1a6d-e550-0410-aec6-3dcde31c8c00
This commit is contained in:
parent
9bc3d1a8fe
commit
7717f2366f
@ -946,6 +946,15 @@ class V8_EXPORT UnboundScript {
|
||||
int GetId();
|
||||
Handle<Value> GetScriptName();
|
||||
|
||||
/**
|
||||
* Data read from magic sourceURL comments.
|
||||
*/
|
||||
Handle<Value> GetSourceURL();
|
||||
/**
|
||||
* Data read from magic sourceMappingURL comments.
|
||||
*/
|
||||
Handle<Value> GetSourceMappingURL();
|
||||
|
||||
/**
|
||||
* Returns zero based line number of the code_pos location in the script.
|
||||
* -1 will be returned if no information available.
|
||||
|
@ -585,6 +585,77 @@ Handle<AccessorInfo> Accessors::ScriptLineEndsInfo(
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Accessors::ScriptSourceUrl
|
||||
//
|
||||
|
||||
|
||||
void Accessors::ScriptSourceUrlGetter(
|
||||
v8::Local<v8::String> name,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
||||
DisallowHeapAllocation no_allocation;
|
||||
HandleScope scope(isolate);
|
||||
Object* object = *Utils::OpenHandle(*info.This());
|
||||
Object* url = Script::cast(JSValue::cast(object)->value())->source_url();
|
||||
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
|
||||
}
|
||||
|
||||
|
||||
void Accessors::ScriptSourceUrlSetter(
|
||||
v8::Local<v8::String> name,
|
||||
v8::Local<v8::Value> value,
|
||||
const v8::PropertyCallbackInfo<void>& info) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
Handle<AccessorInfo> Accessors::ScriptSourceUrlInfo(
|
||||
Isolate* isolate, PropertyAttributes attributes) {
|
||||
return MakeAccessor(isolate,
|
||||
isolate->factory()->source_url_string(),
|
||||
&ScriptSourceUrlGetter,
|
||||
&ScriptSourceUrlSetter,
|
||||
attributes);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Accessors::ScriptSourceMappingUrl
|
||||
//
|
||||
|
||||
|
||||
void Accessors::ScriptSourceMappingUrlGetter(
|
||||
v8::Local<v8::String> name,
|
||||
const v8::PropertyCallbackInfo<v8::Value>& info) {
|
||||
i::Isolate* isolate = reinterpret_cast<i::Isolate*>(info.GetIsolate());
|
||||
DisallowHeapAllocation no_allocation;
|
||||
HandleScope scope(isolate);
|
||||
Object* object = *Utils::OpenHandle(*info.This());
|
||||
Object* url =
|
||||
Script::cast(JSValue::cast(object)->value())->source_mapping_url();
|
||||
info.GetReturnValue().Set(Utils::ToLocal(Handle<Object>(url, isolate)));
|
||||
}
|
||||
|
||||
|
||||
void Accessors::ScriptSourceMappingUrlSetter(
|
||||
v8::Local<v8::String> name,
|
||||
v8::Local<v8::Value> value,
|
||||
const v8::PropertyCallbackInfo<void>& info) {
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
|
||||
Handle<AccessorInfo> Accessors::ScriptSourceMappingUrlInfo(
|
||||
Isolate* isolate, PropertyAttributes attributes) {
|
||||
return MakeAccessor(isolate,
|
||||
isolate->factory()->source_mapping_url_string(),
|
||||
&ScriptSourceMappingUrlGetter,
|
||||
&ScriptSourceMappingUrlSetter,
|
||||
attributes);
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Accessors::ScriptGetContextData
|
||||
//
|
||||
|
@ -32,6 +32,8 @@ namespace internal {
|
||||
V(ScriptName) \
|
||||
V(ScriptSource) \
|
||||
V(ScriptType) \
|
||||
V(ScriptSourceUrl) \
|
||||
V(ScriptSourceMappingUrl) \
|
||||
V(StringLength)
|
||||
|
||||
// Accessors contains all predefined proxy accessors.
|
||||
|
32
src/api.cc
32
src/api.cc
@ -1633,6 +1633,38 @@ Handle<Value> UnboundScript::GetScriptName() {
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UnboundScript::GetSourceURL() {
|
||||
i::Handle<i::SharedFunctionInfo> obj =
|
||||
i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
|
||||
i::Isolate* isolate = obj->GetIsolate();
|
||||
ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceURL()",
|
||||
return Handle<String>());
|
||||
LOG_API(isolate, "UnboundScript::GetSourceURL");
|
||||
if (obj->script()->IsScript()) {
|
||||
i::Object* url = i::Script::cast(obj->script())->source_url();
|
||||
return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
|
||||
} else {
|
||||
return Handle<String>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Handle<Value> UnboundScript::GetSourceMappingURL() {
|
||||
i::Handle<i::SharedFunctionInfo> obj =
|
||||
i::Handle<i::SharedFunctionInfo>::cast(Utils::OpenHandle(this));
|
||||
i::Isolate* isolate = obj->GetIsolate();
|
||||
ON_BAILOUT(isolate, "v8::UnboundScript::GetSourceMappingURL()",
|
||||
return Handle<String>());
|
||||
LOG_API(isolate, "UnboundScript::GetSourceMappingURL");
|
||||
if (obj->script()->IsScript()) {
|
||||
i::Object* url = i::Script::cast(obj->script())->source_mapping_url();
|
||||
return Utils::ToLocal(i::Handle<i::Object>(url, isolate));
|
||||
} else {
|
||||
return Handle<String>();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Local<Value> Script::Run() {
|
||||
i::Handle<i::Object> obj = Utils::OpenHandle(this, true);
|
||||
// If execution is terminating, Compile(..)->Run() requires this
|
||||
|
@ -1762,7 +1762,7 @@ bool Genesis::InstallNatives() {
|
||||
native_context()->set_script_function(*script_fun);
|
||||
|
||||
Handle<Map> script_map = Handle<Map>(script_fun->initial_map());
|
||||
Map::EnsureDescriptorSlack(script_map, 13);
|
||||
Map::EnsureDescriptorSlack(script_map, 14);
|
||||
|
||||
PropertyAttributes attribs =
|
||||
static_cast<PropertyAttributes>(DONT_ENUM | DONT_DELETE | READ_ONLY);
|
||||
@ -1869,6 +1869,23 @@ bool Genesis::InstallNatives() {
|
||||
script_map->AppendDescriptor(&d);
|
||||
}
|
||||
|
||||
Handle<AccessorInfo> script_source_url =
|
||||
Accessors::ScriptSourceUrlInfo(isolate(), attribs);
|
||||
{
|
||||
CallbacksDescriptor d(Handle<Name>(Name::cast(script_source_url->name())),
|
||||
script_source_url, attribs);
|
||||
script_map->AppendDescriptor(&d);
|
||||
}
|
||||
|
||||
Handle<AccessorInfo> script_source_mapping_url =
|
||||
Accessors::ScriptSourceMappingUrlInfo(isolate(), attribs);
|
||||
{
|
||||
CallbacksDescriptor d(
|
||||
Handle<Name>(Name::cast(script_source_mapping_url->name())),
|
||||
script_source_mapping_url, attribs);
|
||||
script_map->AppendDescriptor(&d);
|
||||
}
|
||||
|
||||
// Allocate the empty script.
|
||||
Handle<Script> script = factory()->NewScript(factory()->empty_string());
|
||||
script->set_type(Smi::FromInt(Script::TYPE_NATIVE));
|
||||
|
@ -290,6 +290,8 @@ namespace internal {
|
||||
V(nan_string, "NaN") \
|
||||
V(RegExp_string, "RegExp") \
|
||||
V(source_string, "source") \
|
||||
V(source_url_string, "source_url") \
|
||||
V(source_mapping_url_string, "source_mapping_url") \
|
||||
V(global_string, "global") \
|
||||
V(ignore_case_string, "ignoreCase") \
|
||||
V(multiline_string, "multiline") \
|
||||
|
@ -560,44 +560,16 @@ function ScriptNameOrSourceURL() {
|
||||
if (this.line_offset > 0 || this.column_offset > 0) {
|
||||
return this.name;
|
||||
}
|
||||
|
||||
// The result is cached as on long scripts it takes noticable time to search
|
||||
// for the sourceURL.
|
||||
if (this.hasCachedNameOrSourceURL) {
|
||||
return this.cachedNameOrSourceURL;
|
||||
if (this.source_url) {
|
||||
return this.source_url;
|
||||
}
|
||||
this.hasCachedNameOrSourceURL = true;
|
||||
|
||||
// TODO(608): the spaces in a regexp below had to be escaped as \040
|
||||
// because this file is being processed by js2c whose handling of spaces
|
||||
// in regexps is broken. Also, ['"] are excluded from allowed URLs to
|
||||
// avoid matches against sources that invoke evals with sourceURL.
|
||||
// A better solution would be to detect these special comments in
|
||||
// the scanner/parser.
|
||||
var source = ToString(this.source);
|
||||
var sourceUrlPos = %StringIndexOf(source, "sourceURL=", 0);
|
||||
this.cachedNameOrSourceURL = this.name;
|
||||
if (sourceUrlPos > 4) {
|
||||
var sourceUrlPattern =
|
||||
/\/\/[#@][\040\t]sourceURL=[\040\t]*([^\s\'\"]*)[\040\t]*$/gm;
|
||||
// Don't reuse lastMatchInfo here, so we create a new array with room
|
||||
// for four captures (array with length one longer than the index
|
||||
// of the fourth capture, where the numbering is zero-based).
|
||||
var matchInfo = new InternalArray(CAPTURE(3) + 1);
|
||||
var match =
|
||||
%_RegExpExec(sourceUrlPattern, source, sourceUrlPos - 4, matchInfo);
|
||||
if (match) {
|
||||
this.cachedNameOrSourceURL =
|
||||
%_SubString(source, matchInfo[CAPTURE(2)], matchInfo[CAPTURE(3)]);
|
||||
}
|
||||
}
|
||||
return this.cachedNameOrSourceURL;
|
||||
return this.name;
|
||||
}
|
||||
|
||||
|
||||
SetUpLockedPrototype(Script,
|
||||
$Array("source", "name", "line_ends", "line_offset", "column_offset",
|
||||
"cachedNameOrSourceURL", "hasCachedNameOrSourceURL" ),
|
||||
$Array("source", "name", "source_url", "source_mapping_url", "line_ends",
|
||||
"line_offset", "column_offset"),
|
||||
$Array(
|
||||
"lineFromPosition", ScriptLineFromPosition,
|
||||
"locationFromPosition", ScriptLocationFromPosition,
|
||||
|
@ -5263,6 +5263,8 @@ ACCESSORS_TO_SMI(Script, eval_from_instructions_offset,
|
||||
kEvalFrominstructionsOffsetOffset)
|
||||
ACCESSORS_TO_SMI(Script, flags, kFlagsOffset)
|
||||
BOOL_ACCESSORS(Script, flags, is_shared_cross_origin, kIsSharedCrossOriginBit)
|
||||
ACCESSORS(Script, source_url, Object, kSourceUrlOffset)
|
||||
ACCESSORS(Script, source_mapping_url, Object, kSourceMappingUrlOffset)
|
||||
|
||||
Script::CompilationType Script::compilation_type() {
|
||||
return BooleanBit::get(flags(), kCompilationTypeBit) ?
|
||||
|
@ -6911,6 +6911,12 @@ class Script: public Struct {
|
||||
// [flags]: Holds an exciting bitfield.
|
||||
DECL_ACCESSORS(flags, Smi)
|
||||
|
||||
// [source_url]: sourceURL from magic comment
|
||||
DECL_ACCESSORS(source_url, Object)
|
||||
|
||||
// [source_url]: sourceMappingURL magic comment
|
||||
DECL_ACCESSORS(source_mapping_url, Object)
|
||||
|
||||
// [compilation_type]: how the the script was compiled. Encoded in the
|
||||
// 'flags' field.
|
||||
inline CompilationType compilation_type();
|
||||
@ -6967,7 +6973,9 @@ class Script: public Struct {
|
||||
kEvalFromSharedOffset + kPointerSize;
|
||||
static const int kFlagsOffset =
|
||||
kEvalFrominstructionsOffsetOffset + kPointerSize;
|
||||
static const int kSize = kFlagsOffset + kPointerSize;
|
||||
static const int kSourceUrlOffset = kFlagsOffset + kPointerSize;
|
||||
static const int kSourceMappingUrlOffset = kSourceUrlOffset + kPointerSize;
|
||||
static const int kSize = kSourceMappingUrlOffset + kPointerSize;
|
||||
|
||||
private:
|
||||
int GetLineNumberWithArray(int code_pos);
|
||||
|
@ -895,6 +895,9 @@ FunctionLiteral* Parser::DoParseProgram(CompilationInfo* info,
|
||||
bool ok = true;
|
||||
int beg_pos = scanner()->location().beg_pos;
|
||||
ParseSourceElements(body, Token::EOS, info->is_eval(), true, &ok);
|
||||
|
||||
HandleSourceURLComments();
|
||||
|
||||
if (ok && strict_mode() == STRICT) {
|
||||
CheckOctalLiteral(beg_pos, scanner()->location().end_pos, &ok);
|
||||
}
|
||||
@ -3882,6 +3885,18 @@ void Parser::RegisterTargetUse(Label* target, Target* stop) {
|
||||
}
|
||||
|
||||
|
||||
void Parser::HandleSourceURLComments() {
|
||||
if (scanner_.source_url()->length() > 0) {
|
||||
info_->script()->set_source_url(
|
||||
*scanner_.source_url()->Internalize(isolate()));
|
||||
}
|
||||
if (scanner_.source_mapping_url()->length() > 0) {
|
||||
info_->script()->set_source_mapping_url(
|
||||
*scanner_.source_mapping_url()->Internalize(isolate()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Parser::ThrowPendingError() {
|
||||
ASSERT(ast_value_factory_->IsInternalized());
|
||||
if (has_pending_error_) {
|
||||
|
@ -796,6 +796,8 @@ class Parser : public ParserBase<ParserTraits> {
|
||||
const AstRawString* function_name, int pos, Variable* fvar,
|
||||
Token::Value fvar_init_op, bool is_generator, bool* ok);
|
||||
|
||||
void HandleSourceURLComments();
|
||||
|
||||
void ThrowPendingError();
|
||||
|
||||
void InternalizeUseCounts();
|
||||
|
@ -19,6 +19,15 @@
|
||||
namespace v8 {
|
||||
namespace internal {
|
||||
|
||||
|
||||
Handle<String> LiteralBuffer::Internalize(Isolate* isolate) const {
|
||||
if (is_one_byte()) {
|
||||
return isolate->factory()->InternalizeOneByteString(one_byte_literal());
|
||||
}
|
||||
return isolate->factory()->InternalizeTwoByteString(two_byte_literal());
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Scanner
|
||||
|
||||
@ -295,6 +304,68 @@ Token::Value Scanner::SkipSingleLineComment() {
|
||||
}
|
||||
|
||||
|
||||
Token::Value Scanner::SkipSourceURLComment() {
|
||||
TryToParseSourceURLComment();
|
||||
while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
|
||||
Advance();
|
||||
}
|
||||
|
||||
return Token::WHITESPACE;
|
||||
}
|
||||
|
||||
|
||||
void Scanner::TryToParseSourceURLComment() {
|
||||
// Magic comments are of the form: //[#@]\s<name>=\s*<value>\s*.* and this
|
||||
// function will just return if it cannot parse a magic comment.
|
||||
if (!unicode_cache_->IsWhiteSpace(c0_))
|
||||
return;
|
||||
Advance();
|
||||
LiteralBuffer name;
|
||||
while (c0_ >= 0 && !unicode_cache_->IsWhiteSpaceOrLineTerminator(c0_) &&
|
||||
c0_ != '=') {
|
||||
name.AddChar(c0_);
|
||||
Advance();
|
||||
}
|
||||
if (!name.is_one_byte()) return;
|
||||
Vector<const uint8_t> name_literal = name.one_byte_literal();
|
||||
LiteralBuffer* value;
|
||||
if (name_literal == STATIC_ASCII_VECTOR("sourceURL")) {
|
||||
value = &source_url_;
|
||||
} else if (name_literal == STATIC_ASCII_VECTOR("sourceMappingURL")) {
|
||||
value = &source_mapping_url_;
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
if (c0_ != '=')
|
||||
return;
|
||||
Advance();
|
||||
value->Reset();
|
||||
while (c0_ >= 0 && unicode_cache_->IsWhiteSpace(c0_)) {
|
||||
Advance();
|
||||
}
|
||||
while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
|
||||
// Disallowed characters.
|
||||
if (c0_ == '"' || c0_ == '\'') {
|
||||
value->Reset();
|
||||
return;
|
||||
}
|
||||
if (unicode_cache_->IsWhiteSpace(c0_)) {
|
||||
break;
|
||||
}
|
||||
value->AddChar(c0_);
|
||||
Advance();
|
||||
}
|
||||
// Allow whitespace at the end.
|
||||
while (c0_ >= 0 && !unicode_cache_->IsLineTerminator(c0_)) {
|
||||
if (!unicode_cache_->IsWhiteSpace(c0_)) {
|
||||
value->Reset();
|
||||
break;
|
||||
}
|
||||
Advance();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Token::Value Scanner::SkipMultiLineComment() {
|
||||
ASSERT(c0_ == '*');
|
||||
Advance();
|
||||
@ -459,7 +530,14 @@ void Scanner::Scan() {
|
||||
// / // /* /=
|
||||
Advance();
|
||||
if (c0_ == '/') {
|
||||
token = SkipSingleLineComment();
|
||||
Advance();
|
||||
if (c0_ == '@' || c0_ == '#') {
|
||||
Advance();
|
||||
token = SkipSourceURLComment();
|
||||
} else {
|
||||
PushBack(c0_);
|
||||
token = SkipSingleLineComment();
|
||||
}
|
||||
} else if (c0_ == '*') {
|
||||
token = SkipMultiLineComment();
|
||||
} else if (c0_ == '=') {
|
||||
|
@ -216,14 +216,14 @@ class LiteralBuffer {
|
||||
position_ += kUC16Size;
|
||||
}
|
||||
|
||||
bool is_one_byte() { return is_one_byte_; }
|
||||
bool is_one_byte() const { return is_one_byte_; }
|
||||
|
||||
bool is_contextual_keyword(Vector<const char> keyword) {
|
||||
bool is_contextual_keyword(Vector<const char> keyword) const {
|
||||
return is_one_byte() && keyword.length() == position_ &&
|
||||
(memcmp(keyword.start(), backing_store_.start(), position_) == 0);
|
||||
}
|
||||
|
||||
Vector<const uint16_t> two_byte_literal() {
|
||||
Vector<const uint16_t> two_byte_literal() const {
|
||||
ASSERT(!is_one_byte_);
|
||||
ASSERT((position_ & 0x1) == 0);
|
||||
return Vector<const uint16_t>(
|
||||
@ -231,14 +231,14 @@ class LiteralBuffer {
|
||||
position_ >> 1);
|
||||
}
|
||||
|
||||
Vector<const uint8_t> one_byte_literal() {
|
||||
Vector<const uint8_t> one_byte_literal() const {
|
||||
ASSERT(is_one_byte_);
|
||||
return Vector<const uint8_t>(
|
||||
reinterpret_cast<const uint8_t*>(backing_store_.start()),
|
||||
position_);
|
||||
}
|
||||
|
||||
int length() {
|
||||
int length() const {
|
||||
return is_one_byte_ ? position_ : (position_ >> 1);
|
||||
}
|
||||
|
||||
@ -247,6 +247,8 @@ class LiteralBuffer {
|
||||
is_one_byte_ = true;
|
||||
}
|
||||
|
||||
Handle<String> Internalize(Isolate* isolate) const;
|
||||
|
||||
private:
|
||||
static const int kInitialCapacity = 16;
|
||||
static const int kGrowthFactory = 4;
|
||||
@ -451,6 +453,11 @@ class Scanner {
|
||||
// be empty).
|
||||
bool ScanRegExpFlags();
|
||||
|
||||
const LiteralBuffer* source_url() const { return &source_url_; }
|
||||
const LiteralBuffer* source_mapping_url() const {
|
||||
return &source_mapping_url_;
|
||||
}
|
||||
|
||||
private:
|
||||
// The current and look-ahead token.
|
||||
struct TokenDesc {
|
||||
@ -572,6 +579,8 @@ class Scanner {
|
||||
|
||||
bool SkipWhiteSpace();
|
||||
Token::Value SkipSingleLineComment();
|
||||
Token::Value SkipSourceURLComment();
|
||||
void TryToParseSourceURLComment();
|
||||
Token::Value SkipMultiLineComment();
|
||||
// Scans a possible HTML comment -- begins with '<!'.
|
||||
Token::Value ScanHtmlComment();
|
||||
@ -606,6 +615,10 @@ class Scanner {
|
||||
LiteralBuffer literal_buffer1_;
|
||||
LiteralBuffer literal_buffer2_;
|
||||
|
||||
// Values parsed from magic comments.
|
||||
LiteralBuffer source_url_;
|
||||
LiteralBuffer source_mapping_url_;
|
||||
|
||||
TokenDesc current_; // desc for current token (as returned by Next())
|
||||
TokenDesc next_; // desc for next token (one token look-ahead)
|
||||
|
||||
|
11
src/vector.h
11
src/vector.h
@ -100,6 +100,17 @@ class Vector {
|
||||
input.length() * sizeof(S) / sizeof(T));
|
||||
}
|
||||
|
||||
bool operator==(const Vector<T>& other) const {
|
||||
if (length_ != other.length_) return false;
|
||||
if (start_ == other.start_) return true;
|
||||
for (int i = 0; i < length_; ++i) {
|
||||
if (start_[i] != other.start_[i]) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
protected:
|
||||
void set_start(T* start) { start_ = start; }
|
||||
|
||||
|
@ -22761,3 +22761,85 @@ TEST(CrossActivationEval) {
|
||||
Local<Value> result = CompileRun("CallEval();");
|
||||
CHECK_EQ(result, v8::Integer::New(isolate, 1));
|
||||
}
|
||||
|
||||
|
||||
void SourceURLHelper(const char* source, const char* expected_source_url,
|
||||
const char* expected_source_mapping_url) {
|
||||
Local<Script> script = v8_compile(source);
|
||||
if (expected_source_url != NULL) {
|
||||
v8::String::Utf8Value url(script->GetUnboundScript()->GetSourceURL());
|
||||
CHECK_EQ(expected_source_url, *url);
|
||||
} else {
|
||||
CHECK(script->GetUnboundScript()->GetSourceURL()->IsUndefined());
|
||||
}
|
||||
if (expected_source_mapping_url != NULL) {
|
||||
v8::String::Utf8Value url(
|
||||
script->GetUnboundScript()->GetSourceMappingURL());
|
||||
CHECK_EQ(expected_source_mapping_url, *url);
|
||||
} else {
|
||||
CHECK(script->GetUnboundScript()->GetSourceMappingURL()->IsUndefined());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
TEST(ScriptSourceURLAndSourceMappingURL) {
|
||||
LocalContext env;
|
||||
v8::Isolate* isolate = env->GetIsolate();
|
||||
v8::HandleScope scope(isolate);
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=bar1.js\n", "bar1.js", NULL);
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceMappingURL=bar2.js\n", NULL, "bar2.js");
|
||||
|
||||
// Both sourceURL and sourceMappingURL.
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=bar3.js\n"
|
||||
"//# sourceMappingURL=bar4.js\n", "bar3.js", "bar4.js");
|
||||
|
||||
// Two source URLs; the first one is ignored.
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=ignoreme.js\n"
|
||||
"//# sourceURL=bar5.js\n", "bar5.js", NULL);
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceMappingURL=ignoreme.js\n"
|
||||
"//# sourceMappingURL=bar6.js\n", NULL, "bar6.js");
|
||||
|
||||
// SourceURL or sourceMappingURL in the middle of the script.
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=bar7.js\n"
|
||||
"function baz() {}\n", "bar7.js", NULL);
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceMappingURL=bar8.js\n"
|
||||
"function baz() {}\n", NULL, "bar8.js");
|
||||
|
||||
// Too much whitespace.
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=bar9.js\n"
|
||||
"//# sourceMappingURL=bar10.js\n", NULL, NULL);
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL =bar11.js\n"
|
||||
"//# sourceMappingURL =bar12.js\n", NULL, NULL);
|
||||
|
||||
// Disallowed characters in value.
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=bar13 .js \n"
|
||||
"//# sourceMappingURL=bar14 .js \n",
|
||||
NULL, NULL);
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=bar15\t.js \n"
|
||||
"//# sourceMappingURL=bar16\t.js \n",
|
||||
NULL, NULL);
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=bar17'.js \n"
|
||||
"//# sourceMappingURL=bar18'.js \n",
|
||||
NULL, NULL);
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL=bar19\".js \n"
|
||||
"//# sourceMappingURL=bar20\".js \n",
|
||||
NULL, NULL);
|
||||
|
||||
// Not too much whitespace.
|
||||
SourceURLHelper("function foo() {}\n"
|
||||
"//# sourceURL= bar21.js \n"
|
||||
"//# sourceMappingURL= bar22.js \n", "bar21.js", "bar22.js");
|
||||
}
|
||||
|
@ -85,9 +85,11 @@ function listener(event, exec_state, event_data, data) {
|
||||
assertTrue('context' in msg.body.script);
|
||||
|
||||
// Check that we pick script name from //# sourceURL, iff present
|
||||
assertEquals(current_source.indexOf('sourceURL') >= 0 ?
|
||||
'myscript.js' : undefined,
|
||||
event_data.script().name());
|
||||
if (event == Debug.DebugEvent.AfterCompile) {
|
||||
assertEquals(current_source.indexOf('sourceURL') >= 0 ?
|
||||
'myscript.js' : undefined,
|
||||
event_data.script().name());
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
exception = e
|
||||
|
Loading…
Reference in New Issue
Block a user