Skip to content

Commit 95ec10b

Browse files
fix: handle webpack source maps when library is set
In case the `library` path is set in webpack.config.js file, the URLs in sourceMaps are generated in a way that is not expected for our parser - currently we expect `webpack:///<path>`, while it becomes `webpack://<library>/<path>`. To handle this, add the correct sourceMapPathOverrides in case the user had not specified it already. Add unit tests and add as devDependency `@types/sinon`. However, the project cannot be transpiled with the current TypeScript version (2.6) when this package is installed, so update TypeScript to latest version. Use proxyquire in the tests to mock the require of the webpack.config.js file.
1 parent ff44b9d commit 95ec10b

5 files changed

+92
-14
lines changed

package.json

+6-3
Original file line numberDiff line numberDiff line change
@@ -36,14 +36,17 @@
3636
"@types/lodash": "4.14.121",
3737
"@types/mocha": "5.2.6",
3838
"@types/node": "6.0.46",
39+
"@types/proxyquire": "1.3.28",
3940
"@types/semver": "5.5.0",
41+
"@types/sinon": "7.0.13",
4042
"@types/universal-analytics": "0.4.1",
4143
"cpx": "1.5.0",
4244
"mocha": "5.2.0",
43-
"sinon": "5.1.1",
44-
"tslint": "5.10.0",
45+
"proxyquire": "2.1.3",
46+
"sinon": "7.4.2",
47+
"tslint": "5.19.0",
4548
"tslint-eslint-rules": "5.4.0",
46-
"typescript": "2.6.2",
49+
"typescript": "3.6.2",
4750
"vsce": "1.57.1",
4851
"vscode": "1.1.30",
4952
"vscode-debugprotocol": "1.34.0"

src/debug-adapter/nativeScriptDebugAdapter.ts

+23-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ import {
88
ISetBreakpointsResponseBody,
99
ITelemetryPropertyCollector,
1010
} from 'vscode-chrome-debug-core';
11-
import { Event, TerminatedEvent } from 'vscode-debugadapter';
11+
import { Event, logger, TerminatedEvent } from 'vscode-debugadapter';
1212
import { DebugProtocol } from 'vscode-debugprotocol';
1313
import * as extProtocol from '../common/extensionProtocol';
1414
import { NativeScriptSourceMapTransformer } from './nativeScriptSourceMapTransformer';
@@ -179,13 +179,32 @@ export class NativeScriptDebugAdapter extends ChromeDebugAdapter {
179179
args.sourceMapPathOverrides = {};
180180
}
181181

182-
if (!args.sourceMapPathOverrides['webpack:///*']) {
183-
const appDirPath = this.getAppDirPath(args.webRoot) || 'app';
184-
const fullAppDirPath = join(args.webRoot, appDirPath);
182+
const appDirPath = this.getAppDirPath(args.webRoot) || 'app';
183+
const fullAppDirPath = join(args.webRoot, appDirPath);
185184

185+
if (!args.sourceMapPathOverrides['webpack:///*']) {
186186
args.sourceMapPathOverrides['webpack:///*'] = `${fullAppDirPath}/*`;
187187
}
188188

189+
const webpackConfigFile = join(`./${args.webRoot}`, 'webpack.config.js');
190+
191+
if (existsSync(webpackConfigFile)) {
192+
try {
193+
const webpackConfig = require(webpackConfigFile);
194+
const platform = args.platform && args.platform.toLowerCase();
195+
const config = webpackConfig({ [`${platform}`]: platform });
196+
197+
if (config && config.output && config.output.library) {
198+
const sourceMapPathOverrideWithLib = `webpack://${config.output.library}/*`;
199+
200+
args.sourceMapPathOverrides[sourceMapPathOverrideWithLib] = args.sourceMapPathOverrides[sourceMapPathOverrideWithLib] ||
201+
`${fullAppDirPath}/*`;
202+
}
203+
} catch (err) {
204+
logger.warn(`Error when trying to require webpack.config.js file from path '${webpackConfigFile}'. Error is: ${err}`);
205+
}
206+
}
207+
189208
return args;
190209
}
191210

src/tests/nativeScriptDebugAdapter.tests.ts

+62-5
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
1+
import * as fs from 'fs';
12
import * as _ from 'lodash';
3+
import { join } from 'path';
4+
import * as proxyquire from 'proxyquire';
25
import * as sinon from 'sinon';
36
import { ChromeDebugAdapter } from 'vscode-chrome-debug-core';
47
import { Event } from 'vscode-debugadapter';
58
import * as extProtocol from '../common/extensionProtocol';
6-
import { NativeScriptDebugAdapter } from '../debug-adapter/nativeScriptDebugAdapter';
9+
const appRoot = 'appRootMock';
10+
const webpackConfigFunctionStub = sinon.stub();
11+
12+
proxyquire.noCallThru();
13+
const nativeScriptDebugAdapterLib = proxyquire('../debug-adapter/nativeScriptDebugAdapter', {
14+
[join(appRoot, 'webpack.config.js')]: webpackConfigFunctionStub,
15+
});
716

817
const examplePort = 456;
918

@@ -17,7 +26,7 @@ const customMessagesResponses = {
1726
};
1827

1928
const defaultArgsMock: any = {
20-
appRoot: 'appRootMock',
29+
appRoot,
2130
diagnosticLogging: true,
2231
platform: 'android',
2332
request: 'attach',
@@ -67,7 +76,7 @@ describe('NativeScriptDebugAdapter', () => {
6776
setTransformOptions: () => undefined,
6877
};
6978

70-
nativeScriptDebugAdapter = new NativeScriptDebugAdapter({
79+
nativeScriptDebugAdapter = new nativeScriptDebugAdapterLib.NativeScriptDebugAdapter({
7180
chromeConnection: mockConstructor(chromeConnectionMock),
7281
pathTransformer: mockConstructor(pathTransformerMock),
7382
sourceMapTransformer: mockConstructor(sourceMapTransformer),
@@ -83,7 +92,11 @@ describe('NativeScriptDebugAdapter', () => {
8392

8493
platforms.forEach((platform) => {
8594
launchMethods.forEach((method) => {
86-
const argsMock = _.merge({}, defaultArgsMock, { platform, request: method });
95+
let argsMock: any;
96+
97+
beforeEach(() => {
98+
argsMock = _.merge({}, defaultArgsMock, { platform, request: method });
99+
});
87100

88101
it(`${method} for ${platform} should raise debug start event`, async () => {
89102
const spy = sinon.spy(chromeSessionMock, 'sendEvent');
@@ -121,7 +134,51 @@ describe('NativeScriptDebugAdapter', () => {
121134

122135
sinon.assert.calledWith(spy, sinon.match({
123136
trace: true,
124-
webRoot: 'appRootMock',
137+
webRoot: appRoot,
138+
}));
139+
});
140+
141+
it(`${method} for ${platform} should add sourceMapPathOverrides data`, async () => {
142+
const spy = sinon.spy(ChromeDebugAdapter.prototype, 'attach');
143+
const existsSyncStub = sinon.stub(fs, 'existsSync');
144+
145+
existsSyncStub.returns(true);
146+
webpackConfigFunctionStub
147+
.withArgs({ [platform]: platform })
148+
.returns({ output: { library: 'myLib' } });
149+
150+
await nativeScriptDebugAdapter[method](argsMock);
151+
152+
existsSyncStub.restore();
153+
sinon.assert.calledWith(spy, sinon.match({
154+
sourceMapPathOverrides: {
155+
'webpack:///*': `${join(appRoot, 'app')}/*`,
156+
'webpack://myLib/*': `${join(appRoot, 'app')}/*`,
157+
},
158+
trace: true,
159+
webRoot: appRoot,
160+
}));
161+
162+
});
163+
164+
it(`${method} for ${platform} should not fail when unable to require webpack.config.js`, async () => {
165+
const spy = sinon.spy(ChromeDebugAdapter.prototype, 'attach');
166+
const existsSyncStub = sinon.stub(fs, 'existsSync');
167+
168+
existsSyncStub.returns(true);
169+
webpackConfigFunctionStub
170+
.withArgs({ [platform]: platform })
171+
.throws(new Error('test'));
172+
173+
await nativeScriptDebugAdapter[method](argsMock);
174+
175+
existsSyncStub.restore();
176+
sinon.assert.calledWith(spy, sinon.match({
177+
sourceMapPathOverrides: {
178+
'webpack:///*': `${join(appRoot, 'app')}/*`,
179+
},
180+
trace: true,
181+
webRoot: appRoot,
125182
}));
126183
});
127184

src/tests/nativeScriptTargetDiscovery.tests.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ describe('NativeScriptTargetDiscovery', () => {
2121
});
2222

2323
it(`getTargets calls getTarget`, async () => {
24-
const testTarget = {
24+
const testTarget: any = {
2525
devtoolsFrontendUrl: 'url',
2626
webSocketDebuggerUrl: 'socket',
2727
};

tslint.json

-1
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@
2727
"check-type"
2828
],
2929
"newline-before-return": true,
30-
"no-unused-variable": true,
3130
"no-duplicate-variable": true,
3231
"no-unused-expression": [
3332
true,

0 commit comments

Comments
 (0)