Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into remote-fs
Browse files Browse the repository at this point in the history
  • Loading branch information
digeff committed Aug 25, 2020
2 parents a3cf62c + 2eadab0 commit 90a509a
Show file tree
Hide file tree
Showing 13 changed files with 94 additions and 51 deletions.
8 changes: 8 additions & 0 deletions gulpfile.js
Original file line number Diff line number Diff line change
Expand Up @@ -273,6 +273,11 @@ gulp.task('flatSessionBundle:webpack-bundle', async () => {
return runWebpack({ packages, devtool: 'nosources-source-map' });
});

gulp.task('package:bootloader-as-cdp', done => {
const bootloaderFilePath = path.resolve(distSrcDir, 'bootloader.bundle.js');
fs.appendFile(bootloaderFilePath, '\n//# sourceURL=bootloader.bundle.cdp', done);
});

/** Run webpack to bundle into the VS debug server */
gulp.task('vsDebugServerBundle:webpack-bundle', async () => {
const packages = [{ entry: `${buildSrcDir}/vsDebugServer.js`, library: true }];
Expand Down Expand Up @@ -373,6 +378,7 @@ gulp.task(
'compile:static',
'compile:dynamic',
'package:webpack-bundle',
'package:bootloader-as-cdp',
'package:copy-extension-files',
'nls:bundle-create',
'package:createVSIX',
Expand All @@ -385,6 +391,7 @@ gulp.task(
'clean',
'compile',
'flatSessionBundle:webpack-bundle',
'package:bootloader-as-cdp',
'package:copy-extension-files',
gulp.parallel('nls:bundle-download', 'nls:bundle-create'),
),
Expand All @@ -398,6 +405,7 @@ gulp.task(
'compile',
'vsDebugServerBundle:webpack-bundle',
'flatSessionBundle:webpack-bundle',
'package:bootloader-as-cdp',
'package:copy-extension-files',
gulp.parallel('nls:bundle-download', 'nls:bundle-create'),
),
Expand Down
7 changes: 0 additions & 7 deletions src/adapter/breakpoints/conditions/logPoint.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,6 @@ import { RuntimeLogPoint } from './runtimeLogPoint';
*/
@injectable()
export class LogPointCompiler {
/**
* Gets whether the url looks like a log point source.
*/
public static isLogPointUrl(url: string) {
return /logpoint-[a-f0-9]+\.cdp$/.test(url);
}

constructor(
@inject(ILogger) private readonly logger: ILogger,
@inject(IEvaluator) private readonly evaluator: IEvaluator,
Expand Down
10 changes: 5 additions & 5 deletions src/adapter/completions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/

import { inject, injectable } from 'inversify';
import * as ts from 'typescript';
import Dap from '../dap/api';
import Cdp from '../cdp/api';
import { StackFrame } from './stackTrace';
import { ICdpApi } from '../cdp/connection';
import { positionToOffset } from '../common/sourceUtils';
import { enumerateProperties, enumeratePropertiesTemplate } from './templates/enumerateProperties';
import { injectable, inject } from 'inversify';
import Dap from '../dap/api';
import { IEvaluator, returnValueStr } from './evaluator';
import { ICdpApi } from '../cdp/connection';
import { StackFrame } from './stackTrace';
import { enumerateProperties, enumeratePropertiesTemplate } from './templates/enumerateProperties';

/**
* Context in which a completion is being evaluated.
Expand Down
38 changes: 28 additions & 10 deletions src/adapter/evaluator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,12 @@
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/

import Cdp from '../cdp/api';
import * as ts from 'typescript';
import { randomBytes } from 'crypto';
import { inject, injectable } from 'inversify';
import * as ts from 'typescript';
import Cdp from '../cdp/api';
import { ICdpApi } from '../cdp/connection';
import { getSourceSuffix } from './templates';

export const returnValueStr = '$returnValue';

Expand Down Expand Up @@ -34,26 +35,34 @@ export interface IEvaluator {
* whether we actually need to pause for a custom log evaluation, or whether
* we can just send the logpoint as the breakpoint condition directly.
*/
prepare(expression: string): { canEvaluateDirectly: boolean; invoke: PreparedCallFrameExpr };
prepare(
expression: string,
isInternalScript?: boolean,
): { canEvaluateDirectly: boolean; invoke: PreparedCallFrameExpr };

/**
* Evaluates the expression on a call frame. This allows
* referencing the $returnValue
*/
evaluate(
params: Cdp.Debugger.EvaluateOnCallFrameParams,
isInternalScript?: boolean,
): Promise<Cdp.Debugger.EvaluateOnCallFrameResult>;

/**
* Evaluates the expression the runtime.
*/
evaluate(params: Cdp.Runtime.EvaluateParams): Promise<Cdp.Runtime.EvaluateResult>;
evaluate(
params: Cdp.Runtime.EvaluateParams,
isInternalScript?: boolean,
): Promise<Cdp.Runtime.EvaluateResult>;

/**
* Evaluates the expression the runtime or call frame.
*/
evaluate(
params: Cdp.Runtime.EvaluateParams | Cdp.Debugger.EvaluateOnCallFrameParams,
isInternalScript?: boolean,
): Promise<Cdp.Runtime.EvaluateResult | Cdp.Debugger.EvaluateOnCallFrameResult>;

/**
Expand Down Expand Up @@ -123,11 +132,20 @@ export class Evaluator implements IEvaluator {
*/
public evaluate(
params: Cdp.Debugger.EvaluateOnCallFrameParams,
isInternalScript?: boolean,
): Promise<Cdp.Debugger.EvaluateOnCallFrameResult>;
public evaluate(params: Cdp.Runtime.EvaluateParams): Promise<Cdp.Runtime.EvaluateResult>;
public evaluate(
params: Cdp.Runtime.EvaluateParams,
isInternalScript?: boolean,
): Promise<Cdp.Runtime.EvaluateResult>;
public async evaluate(
params: Cdp.Debugger.EvaluateOnCallFrameParams | Cdp.Runtime.EvaluateParams,
isInternalScript = true,
) {
if (isInternalScript) {
params = { ...params, expression: params.expression + getSourceSuffix() };
}

// no call frame means there will not be any relevant $returnValue to reference
if (!('callFrameId' in params)) {
return this.cdp.Runtime.evaluate(params);
Expand All @@ -146,14 +164,14 @@ export class Evaluator implements IEvaluator {
if (objectId) {
await this.cdp.Runtime.callFunctionOn({
objectId,
functionDeclaration: `function() { globalThis.${hoistedVar} = this; ${dehoist}; }`,
functionDeclaration: `function() { globalThis.${hoistedVar} = this; ${dehoist}; ${getSourceSuffix()} }`,
});
} else {
await this.cdp.Runtime.evaluate({
expression: `
globalThis.${hoistedVar} = ${JSON.stringify(this.returnValue?.value)};
${dehoist};
`,
expression:
`globalThis.${hoistedVar} = ${JSON.stringify(this.returnValue?.value)};` +
`${dehoist};` +
getSourceSuffix(),
});
}
}
Expand Down
3 changes: 2 additions & 1 deletion src/adapter/scriptSkipper/implementation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
SourceContainer,
SourceFromMap,
} from '../sources';
import { getSourceSuffix } from '../templates';

interface ISharedSkipToggleEvent {
rootTargetId: string;
Expand Down Expand Up @@ -267,7 +268,7 @@ export class ScriptSkipper {
private async _initNodeInternals(target: ITarget): Promise<void> {
if (target.type() === 'node' && this._nodeInternalsGlobs && !this._allNodeInternals) {
const evalResult = await this.cdp.Runtime.evaluate({
expression: "require('module').builtinModules",
expression: "require('module').builtinModules" + getSourceSuffix(),
returnByValue: true,
includeCommandLineAPI: true,
});
Expand Down
8 changes: 8 additions & 0 deletions src/adapter/sources.ts
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,14 @@ type ContentGetter = () => Promise<string | undefined>;
// Each source map has a number of compiled sources referncing it.
type SourceMapData = { compiled: Set<ISourceWithMap>; map?: SourceMap; loaded: Promise<void> };

export const enum SourceConstants {
/**
* Extension of evaluated sources internal to the debugger. Sources with
* this suffix will be ignored when displaying sources or stacktracees.
*/
InternalExtension = '.cdp',
}

export type SourceMapTimeouts = {
// This is a source map loading delay used for testing.
load: number;
Expand Down
19 changes: 7 additions & 12 deletions src/adapter/stackTrace.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,8 @@ import Cdp from '../cdp/api';
import Dap from '../dap/api';
import { asyncScopesNotAvailable } from '../dap/errors';
import { ProtocolError } from '../dap/protocolError';
import { LogPointCompiler } from './breakpoints/conditions/logPoint';
import { shouldSmartStepStackFrame } from './smartStepping';
import { IPreferredUiLocation } from './sources';
import { IPreferredUiLocation, SourceConstants } from './sources';
import { RawLocation, Thread } from './threads';
import { IExtraProperty, IScopeRef } from './variables';

Expand All @@ -24,18 +23,14 @@ export class StackTrace {
public static fromRuntime(
thread: Thread,
stack: Cdp.Runtime.StackTrace,
frameLimit?: number,
frameLimit = Infinity,
): StackTrace {
const result = new StackTrace(thread);
const callFrames = stack.callFrames;

// Remove any frames on top that are within a log point.
while (callFrames.length && LogPointCompiler.isLogPointUrl(callFrames[0].url)) {
callFrames.splice(0, 1);
}

for (const callFrame of frameLimit ? stack.callFrames.slice(0, frameLimit) : stack.callFrames) {
result._frames.push(StackFrame.fromRuntime(thread, callFrame));
for (let frameNo = 0; frameNo < stack.callFrames.length && frameLimit > 0; frameNo++) {
if (!stack.callFrames[frameNo].url.endsWith(SourceConstants.InternalExtension)) {
result._frames.push(StackFrame.fromRuntime(thread, stack.callFrames[frameNo]));
frameLimit--;
}
}

if (stack.parentId) {
Expand Down
12 changes: 10 additions & 2 deletions src/adapter/templates/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,16 @@
* Copyright (C) Microsoft Corporation. All rights reserved.
*--------------------------------------------------------*/

import { randomBytes } from 'crypto';
import * as ts from 'typescript';
import Cdp from '../../cdp/api';
import { SourceConstants } from '../sources';

/**
* Gets the suffix containing the `sourceURL` to mark a script as internal.
*/
export const getSourceSuffix = () =>
`\n//# sourceURL=eval-${randomBytes(4).toString('hex')}${SourceConstants.InternalExtension}\n`;

/**
* Creates a template for the given function that replaces its arguments
Expand Down Expand Up @@ -105,7 +113,7 @@ export function templateFunctionStr<Args extends string[]>(
return (...args) => `(() => {
${args.map((a, i) => `let __args${i} = ${a}`).join('; ')};
${body}
})();`;
})();${getSourceSuffix()}`;
}

/**
Expand All @@ -129,7 +137,7 @@ type RemoteObjectWithType<R, ByValue> = ByValue extends true
* arguments should be simple objects.
*/
export function remoteFunction<Args extends unknown[], R>(fn: string | ((...args: Args) => R)) {
const stringified = '' + fn;
const stringified = ('' + fn).replace('}', getSourceSuffix() + '}');

// Some ugly typing here, but it gets us type safety. Mainly we want to:
// 1. Have args that extend the function arg and omit the args we provide (easy)
Expand Down
7 changes: 7 additions & 0 deletions src/adapter/threads.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import {
IUiLocation,
rawToUiOffset,
Source,
SourceConstants,
SourceContainer,
} from './sources';
import { StackFrame, StackTrace } from './stackTrace';
Expand Down Expand Up @@ -425,6 +426,7 @@ export class Thread implements IVariableStoreDelegate {
...params,
contextId: this._selectedContext ? this._selectedContext.description.id : undefined,
},
/* isInternalScript= */ false,
);

// Report result for repl immediately so that the user could see the expression they entered.
Expand Down Expand Up @@ -1096,6 +1098,11 @@ export class Thread implements IVariableStoreDelegate {
}

private _onScriptParsed(event: Cdp.Debugger.ScriptParsedEvent) {
if (event.url.endsWith(SourceConstants.InternalExtension)) {
// The customer doesn't care about the internal cdp files, so skip this event
return;
}

if (this._sourceContainer.scriptsById.has(event.scriptId)) {
return;
}
Expand Down
10 changes: 5 additions & 5 deletions src/adapter/variables.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import Dap from '../dap/api';
import * as errors from '../dap/errors';
import * as objectPreview from './objectPreview';
import { StackTrace } from './stackTrace';
import { RemoteException } from './templates';
import { getSourceSuffix, RemoteException } from './templates';
import { getArrayProperties } from './templates/getArrayProperties';
import { getArraySlots } from './templates/getArraySlots';
import { invokeGetter } from './templates/invokeGetter';
Expand Down Expand Up @@ -183,13 +183,13 @@ export class VariableStore {
if (!object)
return errors.createSilentError(localize('error.variableNotFound', 'Variable not found'));

const expression = params.value;
if (!expression)
if (!params.value)
return errors.createUserError(localize('error.emptyExpression', 'Cannot set an empty value'));

const expression = params.value + getSourceSuffix();
const evaluateResponse = object.scopeRef
? await object.cdp.Debugger.evaluateOnCallFrame({
expression,
expression: expression,
callFrameId: object.scopeRef.callFrameId,
})
: await object.cdp.Runtime.evaluate({ expression, silent: true });
Expand Down Expand Up @@ -232,7 +232,7 @@ export class VariableStore {
} else {
const setResponse = await object.cdp.Runtime.callFunctionOn({
objectId: object.objectId,
functionDeclaration: `function(a, b) { this[a] = b; }`,
functionDeclaration: `function(a, b) { this[a] = b; ${getSourceSuffix()} }`,
arguments: [
this._toCallArgument(params.name),
this._toCallArgument(evaluateResponse.result),
Expand Down
4 changes: 3 additions & 1 deletion src/targets/node/extensionHostAttacher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*--------------------------------------------------------*/

import { injectable } from 'inversify';
import { getSourceSuffix } from '../../adapter/templates';
import Cdp from '../../cdp/api';
import { DebugType } from '../../common/contributionUtils';
import { LogTag } from '../../common/logging';
Expand Down Expand Up @@ -123,7 +124,8 @@ export class ExtensionHostAttacher extends NodeAttacherBase<IExtensionHostAttach
const result = await cdp.Runtime.evaluate({
contextId: 1,
returnByValue: true,
expression: `Object.assign(process.env, ${JSON.stringify(vars.defined())})`,
expression:
`Object.assign(process.env, ${JSON.stringify(vars.defined())})` + getSourceSuffix(),
});

if (!result) {
Expand Down
8 changes: 5 additions & 3 deletions src/targets/node/nodeAttacher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import { injectable, inject } from 'inversify';
import * as nls from 'vscode-nls';
import { getSourceSuffix } from '../../adapter/templates';
import Cdp from '../../cdp/api';
import { CancellationTokenSource } from '../../common/cancellation';
import { DebugType } from '../../common/contributionUtils';
Expand Down Expand Up @@ -222,9 +223,10 @@ export class NodeAttacher extends NodeAttacherBase<INodeAttachConfiguration> {
const result = await cdp.Runtime.evaluate({
contextId: 1,
returnByValue: true,
expression: `typeof process === 'undefined' ? 'process not defined' : Object.assign(process.env, ${JSON.stringify(
vars.defined(),
)})`,
expression:
`typeof process === 'undefined' ? 'process not defined' : Object.assign(process.env, ${JSON.stringify(
vars.defined(),
)})` + getSourceSuffix(),
});

if (!result) {
Expand Down
Loading

0 comments on commit 90a509a

Please sign in to comment.