1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
|
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WebInspector.SourceMapResource = class SourceMapResource extends WebInspector.Resource
{
constructor(url, sourceMap)
{
super(url, null);
console.assert(url);
console.assert(sourceMap);
this._sourceMap = sourceMap;
var inheritedMIMEType = this._sourceMap.originalSourceCode instanceof WebInspector.Resource ? this._sourceMap.originalSourceCode.syntheticMIMEType : null;
var fileExtension = WebInspector.fileExtensionForURL(url);
var fileExtensionMIMEType = WebInspector.mimeTypeForFileExtension(fileExtension, true);
// FIXME: This is a layering violation. It should use a helper function on the
// Resource base-class to set _mimeType and _type.
this._mimeType = fileExtensionMIMEType || inheritedMIMEType || "text/javascript";
this._type = WebInspector.Resource.typeFromMIMEType(this._mimeType);
// Mark the resource as loaded so it does not show a spinner in the sidebar.
// We will really load the resource the first time content is requested.
this.markAsFinished();
}
// Public
get sourceMap()
{
return this._sourceMap;
}
get sourceMapDisplaySubpath()
{
var sourceMappingBasePathURLComponents = this._sourceMap.sourceMappingBasePathURLComponents;
var resourceURLComponents = this.urlComponents;
// Fallback for JavaScript debuggable named scripts that may not have a complete URL.
if (!resourceURLComponents.path)
resourceURLComponents.path = this.url;
// Different schemes / hosts. Return the host + path of this resource.
if (resourceURLComponents.scheme !== sourceMappingBasePathURLComponents.scheme || resourceURLComponents.host !== sourceMappingBasePathURLComponents.host)
return resourceURLComponents.host + (resourceURLComponents.port ? (":" + resourceURLComponents.port) : "") + resourceURLComponents.path;
// Same host, but not a subpath of the base. This implies a ".." in the relative path.
if (!resourceURLComponents.path.startsWith(sourceMappingBasePathURLComponents.path))
return relativePath(resourceURLComponents.path, sourceMappingBasePathURLComponents.path);
// Same host. Just a subpath of the base.
return resourceURLComponents.path.substring(sourceMappingBasePathURLComponents.path.length, resourceURLComponents.length);
}
requestContentFromBackend(callback)
{
// Revert the markAsFinished that was done in the constructor.
this.revertMarkAsFinished();
var inlineContent = this._sourceMap.sourceContent(this.url);
if (inlineContent) {
// Force inline content to be asynchronous to match the expected load pattern.
// FIXME: We don't know the MIME-type for inline content. Guess by analyzing the content?
// Returns a promise.
return sourceMapResourceLoaded.call(this, {content: inlineContent, mimeType: this.mimeType, statusCode: 200});
}
function sourceMapResourceNotAvailable(error, content, mimeType, statusCode)
{
this.markAsFailed();
return Promise.resolve({
error: WebInspector.UIString("An error occurred trying to load the resource."),
content,
mimeType,
statusCode
});
}
function sourceMapResourceLoadError(error)
{
// There was an error calling NetworkAgent.loadResource.
console.error(error || "There was an unknown error calling NetworkAgent.loadResource.");
this.markAsFailed();
return Promise.resolve({error: WebInspector.UIString("An error occurred trying to load the resource.")});
}
function sourceMapResourceLoaded(parameters)
{
var {error, content, mimeType, statusCode} = parameters;
var base64encoded = false;
if (statusCode >= 400 || error)
return sourceMapResourceNotAvailable(error, content, mimeType, statusCode);
// FIXME: Add support for picking the best MIME-type. Right now the file extension is the best bet.
// The constructor set MIME-type based on the file extension and we ignore mimeType here.
this.markAsFinished();
return Promise.resolve({
content,
mimeType,
base64encoded,
statusCode
});
}
// COMPATIBILITY (iOS 7): Network.loadResource did not exist.
// Also, JavaScript Debuggable with SourceMaps that do not have inlined content may reach this.
if (!window.NetworkAgent || !NetworkAgent.loadResource)
return sourceMapResourceLoadError.call(this);
var frameIdentifier = null;
if (this._sourceMap.originalSourceCode instanceof WebInspector.Resource && this._sourceMap.originalSourceCode.parentFrame)
frameIdentifier = this._sourceMap.originalSourceCode.parentFrame.id;
if (!frameIdentifier)
frameIdentifier = WebInspector.frameResourceManager.mainFrame.id;
return NetworkAgent.loadResource(frameIdentifier, this.url).then(sourceMapResourceLoaded.bind(this)).catch(sourceMapResourceLoadError.bind(this));
}
createSourceCodeLocation(lineNumber, columnNumber)
{
// SourceCodeLocations are always constructed with raw resources and raw locations. Lookup the raw location.
var entry = this._sourceMap.findEntryReversed(this.url, lineNumber);
var rawLineNumber = entry[0];
var rawColumnNumber = entry[1];
// If the raw location is an inline script we need to include that offset.
var originalSourceCode = this._sourceMap.originalSourceCode;
if (originalSourceCode instanceof WebInspector.Script) {
if (rawLineNumber === 0)
rawColumnNumber += originalSourceCode.range.startColumn;
rawLineNumber += originalSourceCode.range.startLine;
}
// Create the SourceCodeLocation and since we already know the the mapped location set it directly.
var location = originalSourceCode.createSourceCodeLocation(rawLineNumber, rawColumnNumber);
location._setMappedLocation(this, lineNumber, columnNumber);
return location;
}
createSourceCodeTextRange(textRange)
{
// SourceCodeTextRanges are always constructed with raw resources and raw locations.
// However, we can provide the most accurate mapped locations in construction.
var startSourceCodeLocation = this.createSourceCodeLocation(textRange.startLine, textRange.startColumn);
var endSourceCodeLocation = this.createSourceCodeLocation(textRange.endLine, textRange.endColumn);
return new WebInspector.SourceCodeTextRange(this._sourceMap.originalSourceCode, startSourceCodeLocation, endSourceCodeLocation);
}
};
|