Skip to content
1 change: 0 additions & 1 deletion src/adapter/resourceProvider/basicResourceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ export class BasicResourceProvider implements IResourceProvider {
return { ok: false, url, error, statusCode: 200 };
}
}

return this.fetchHttp(url, cancellationToken, headers);
}
/**
Expand Down
1 change: 1 addition & 0 deletions src/adapter/scriptSkipper/implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -260,6 +260,7 @@ export class ScriptSkipper {
if (
!skipped &&
source.absolutePath &&
urlUtils.isAbsolute(source.absolutePath) &&
this._testSkipAuthored(urlUtils.absolutePathToFileUrl(source.absolutePath))
) {
this.setIsUrlBlackboxSkipped(url, true);
Expand Down
13 changes: 9 additions & 4 deletions src/adapter/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1082,9 +1082,10 @@ export class SourceContainer {
const todo: Promise<unknown>[] = [];
for (const url of map.sources) {
const absolutePath = await this.sourcePathResolver.urlToAbsolutePath({ url, map });
const resolvedUrl = absolutePath
? utils.absolutePathToFileUrl(absolutePath)
: map.computedSourceUrl(url);
const resolvedUrl =
absolutePath && utils.isAbsolute(absolutePath)
? utils.absolutePathToFileUrl(absolutePath)
: map.computedSourceUrl(url);

const existing = this._sourceMapSourcesByUrl.get(resolvedUrl);
if (existing) {
Expand All @@ -1106,7 +1107,6 @@ export class SourceContainer {
resolvedUrl,
});

const fileUrl = absolutePath && utils.absolutePathToFileUrl(absolutePath);
const smContent = this.sourceMapFactory.guardSourceMapFn(
map,
() => map.sourceContentFor(url, true),
Expand All @@ -1129,6 +1129,10 @@ export class SourceContainer {
}
}

const fileUrl =
absolutePath && utils.isAbsolute(absolutePath)
? utils.absolutePathToFileUrl(absolutePath)
: absolutePath;
const source = new SourceFromMap(
this,
resolvedUrl,
Expand All @@ -1146,6 +1150,7 @@ export class SourceContainer {
);
source.compiledToSourceUrl.set(compiled, url);
compiled.sourceMap.sourceByUrl.set(url, source);

todo.push(this._addSource(source));
}

Expand Down
5 changes: 3 additions & 2 deletions src/adapter/threads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1751,8 +1751,9 @@ export class Thread implements IVariableStoreLocationProvider {
}

const compiledSource =
this._sourceContainer.getSourceByOriginalUrl(urlUtils.absolutePathToFileUrl(chunk.path)) ||
this._sourceContainer.getSourceByOriginalUrl(chunk.path);
this._sourceContainer.getSourceByOriginalUrl(
urlUtils.isAbsolute(chunk.path) ? urlUtils.absolutePathToFileUrl(chunk.path) : chunk.path,
) || this._sourceContainer.getSourceByOriginalUrl(chunk.path);
if (!compiledSource) {
todo.push(chunk.toString());
continue;
Expand Down
14 changes: 9 additions & 5 deletions src/common/sourceMaps/sourceMapResolutionUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,6 @@ export function getFullSourceEntry(sourceRoot: string | undefined, sourcePath: s
if (!sourceRoot.endsWith('/')) {
sourceRoot += '/';
}

return sourceRoot + sourcePath;
}

Expand All @@ -35,12 +34,13 @@ export async function getComputedSourceRoot(
logger: ILogger,
): Promise<string> {
generatedPath = utils.fileUrlToAbsolutePath(generatedPath) || generatedPath;

let absSourceRoot: string;
if (sourceRoot) {
if (utils.isFileUrl(sourceRoot)) {
// sourceRoot points to a local path like "file:///c:/project/src", make it an absolute path
absSourceRoot = utils.fileUrlToAbsolutePath(sourceRoot);
} else if (utils.isValidUrl(sourceRoot)) {
absSourceRoot = sourceRoot;
} else if (utils.isAbsolute(sourceRoot)) {
// sourceRoot is like "/src", should be like http://localhost/src, resolve to a local path using pathMaping.
// If path mappings do not apply (e.g. node), assume that sourceRoot is actually a local absolute path.
Expand Down Expand Up @@ -79,9 +79,13 @@ export async function getComputedSourceRoot(
);
}

absSourceRoot = utils.stripTrailingSlash(absSourceRoot);
absSourceRoot = fixDriveLetterAndSlashes(absSourceRoot);

if (!utils.isValidUrl(absSourceRoot)) {
absSourceRoot = utils.stripTrailingSlash(absSourceRoot);
absSourceRoot = fixDriveLetterAndSlashes(absSourceRoot);
} else {
//guarantees one slash in the end for later join with sources files
absSourceRoot = new URL(absSourceRoot).href;
}
return absSourceRoot;
}

Expand Down
15 changes: 15 additions & 0 deletions src/common/urlUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,16 @@ export function isValidUrl(url: string): boolean {
}
}

export function isValidUrlWithProtocol(url: string): boolean {
try {
const parsed = new URL(url);

return parsed.protocol.toLowerCase() == 'http:' || parsed.protocol.toLowerCase() == 'https:';
} catch (e) {
return false;
}
}

export function escapeForRegExp(s: string): string {
const chars = '^[]{}()\\.^$*+?|-,';

Expand Down Expand Up @@ -301,6 +311,11 @@ export function fileUrlToNetworkPath(urlOrPath: string): string {

// TODO: this does not escape/unescape special characters, but it should.
export function absolutePathToFileUrl(absolutePath: string): string {
if (!isAbsolute(absolutePath)) {
throw new Error(
`You are using the 'absolutePathToFileUrl()' on a string which is not absolute: ${absolutePath}`,
);
}
if (platform === 'win32') {
return 'file:///' + platformPathToUrlPath(absolutePath);
}
Expand Down
24 changes: 11 additions & 13 deletions src/targets/browser/browserPathResolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import {
} from '../../common/sourceMaps/sourceMapResolutionUtils';
import { IUrlResolution } from '../../common/sourcePathResolver';
import * as utils from '../../common/urlUtils';
import { urlToRegex } from '../../common/urlUtils';
import { isValidUrlWithProtocol, urlToRegex } from '../../common/urlUtils';
import { PathMapping } from '../../configuration';
import { ISourcePathResolverOptions, SourcePathResolverBase } from '../sourcePathResolver';

Expand Down Expand Up @@ -87,7 +87,6 @@ export class BrowserSourcePathResolver extends SourcePathResolverBase<IOptions>
if (queryCharacter !== -1 && url.slice(queryCharacter - 4, queryCharacter) !== '.vue') {
url = url.slice(0, queryCharacter);
}

return map ? this.sourceMapSourceToAbsolute(url, map) : this.simpleUrlToAbsolute(url);
}

Expand Down Expand Up @@ -170,7 +169,6 @@ export class BrowserSourcePathResolver extends SourcePathResolverBase<IOptions>
}

url = this.normalizeSourceMapUrl(url);

const { pathMapping } = this.options;
const fullSourceEntry = getFullSourceEntry(map.sourceRoot, url);
let mappedFullSourceEntry = this.sourceMapOverrides.apply(fullSourceEntry);
Expand Down Expand Up @@ -200,18 +198,18 @@ export class BrowserSourcePathResolver extends SourcePathResolverBase<IOptions>
}

if (!path.isAbsolute(url)) {
return properResolve(
await getComputedSourceRoot(
map.sourceRoot,
map.metadata.compiledPath,
pathMapping,
defaultPathMappingResolver,
this.logger,
),
url,
const computedSourceRoot = await getComputedSourceRoot(
map.sourceRoot,
map.metadata.compiledPath,
pathMapping,
defaultPathMappingResolver,
this.logger,
);
if (isValidUrlWithProtocol(computedSourceRoot)) {
return new URL(url, computedSourceRoot).href;
}
return properResolve(computedSourceRoot, url);
}

return fixDriveLetterAndSlashes(url);
}

Expand Down
23 changes: 23 additions & 0 deletions src/test/sources/sources-supports-remote-sources-1424.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@

Source event for
{
reason : new
source : {
name : localhost꞉8001/remote-test/string.ts
path : localhost꞉8001/remote-test/string.ts
sourceReference : <number>
}
}
text/javascript
---------
let i = 0;
i++;
debugger;
i++;
i++;
i++;
i++;
i++;
console.log(i);//ts file

---------
10 changes: 10 additions & 0 deletions src/test/sources/sourcesTest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,16 @@ describe('sources', () => {
handle.assertLog({ substring: true });
});

itIntegrates('supports remote sources (#1424)', async ({ r }) => {
const p = await r.launchUrlAndLoad('index.html');
p.addScriptTag('remote-test/string.js');

const source = await p.waitForSource('string.ts');
await dumpSource(p, source, '');

p.assertLog();
});

itIntegrates('works with relative webpack sourcemaps (#479)', async ({ r }) => {
const p = await r.launchUrl('webpack/relative-paths.html');

Expand Down
10 changes: 10 additions & 0 deletions testWorkspace/web/remote-test/string.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 10 additions & 0 deletions testWorkspace/web/remote-test/string.js.map

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions testWorkspace/web/remote-test/string.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
let i = 0;
i++;
debugger;
i++;
i++;
i++;
i++;
i++;
console.log(i);//ts file