Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
177 changes: 168 additions & 9 deletions types/source-map-support/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,32 +4,111 @@
// Jason Cheatham <https://github.com/jason0x43>
// Alcedo Nathaniel De Guzman Jr <https://github.com/natealcedo>
// Griffin Yourick <https://github.com/tough-griff>
// BendingBender <https://github.com/BendingBender>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped

import { RawSourceMap } from 'source-map';

/**
* Output of retrieveSourceMap().
* From source-map-support:
* The map field may be either a string or the parsed JSON object (i.e.,
* it must be a valid argument to the SourceMapConsumer constructor).
* Output of `retrieveSourceMap()`.
* The map field may be either a string or the parsed JSON object (i.e.,
* it must be a valid argument to the SourceMapConsumer constructor).
*/
export interface UrlAndMap {
url: string;
url?: string | undefined;
map: string | RawSourceMap;
}

export type Environment = 'auto' | 'browser' | 'node';

/**
* Options to install().
*/
export interface Options {
/**
* This module installs two things: a change to the `stack` property on `Error`
* objects and a handler for uncaught exceptions that mimics node's default exception
* handler (the handler can be seen in the demos below). You may want to disable the
* handler if you have your own uncaught exception handler. This can be done by passing
* an argument to the installer.
*
* @example
* import { install } from 'source-map-support';
*
* install({
* handleUncaughtExceptions: false
* });
*/
handleUncaughtExceptions?: boolean | undefined;
/**
* To support files with inline source maps, the `hookRequire` options can be specified,
* which will monitor all source files for inline source maps.
*
* This monkey patches the `require` module loading chain, so is not enabled by default
* and is not recommended for any sort of production usage.
*
* @example
* import { install } from 'source-map-support';
*
* install({
* hookRequire: true
* });
* ```
*/
hookRequire?: boolean | undefined;
/**
* If `true`, the caches are reset before a stack trace formatting operation.
*/
emptyCacheBetweenOperations?: boolean | undefined;
environment?: 'auto' | 'browser' | 'node' | undefined;
/**
* The module will by default assume a browser environment if `XMLHttpRequest` and `window`
* are defined. If either of these do not exist it will instead assume a node environment.
* In some rare cases, e.g. when running a browser emulation and where both variables are
* also set, you can explicitly specify the environment to be either `'browser'` or `'node'`.
*
* @example
* import { install } from 'source-map-support';
*
* install({
* environment: 'node'
* });
*/
environment?: Environment | undefined;
/**
* Disable all other means of retrieving file contents and use only the provided
* `retrieveFile` handler.
*/
overrideRetrieveFile?: boolean | undefined;
/**
* Disable all other means of retrieving source maps and use only the provided
* `retrieveSourceMap` handler.
*/
overrideRetrieveSourceMap?: boolean | undefined;
retrieveFile?(path: string): string;
/**
* Allow sources to be found by methods other than reading the files
* directly from disk.
*/
retrieveFile?(path: string): string | null;
/**
* This module loads source maps from the filesystem by default. You can provide alternate
* loading behavior through a callback as shown below. For example, [Meteor](https://github.com/meteor)
* keeps all source maps cached in memory to avoid disk access.
*
* @example
* import { install } from 'source-map-support';
*
* install({
* retrieveSourceMap(source) {
* if (source === 'compiled.js') {
* return {
* url: 'original.js',
* map: fs.readFileSync('compiled.js.map', 'utf8')
* };
* }
* return null;
* }
* });
*/
retrieveSourceMap?(source: string): UrlAndMap | null;
}

Expand All @@ -39,14 +118,94 @@ export interface Position {
column: number;
}

export function wrapCallSite(frame: any /* StackFrame */): any /* StackFrame */;
export interface State {
nextPosition: Position | null;
curPosition: Position | null;
}

export interface CallSite {
/**
* Value of "this"
*/
getThis(): any;

/**
* Type of "this" as a string.
* This is the name of the function stored in the constructor field of
* "this", if available. Otherwise the object's [[Class]] internal
* property.
*/
getTypeName(): string | null;

/**
* Current function
*/
getFunction(): ((...args: unknown[]) => any) | undefined;

/**
* Name of the current function, typically its name property.
* If a name property is not available an attempt will be made to try
* to infer a name from the function's context.
*/
getFunctionName(): string | null;

/**
* Name of the property [of "this" or one of its prototypes] that holds
* the current function
*/
getMethodName(): string | null;

/**
* Name of the script [if this function was defined in a script]
*/
getFileName(): string | null;

/**
* Current line number [if this function was defined in a script]
*/
getLineNumber(): number | null;

/**
* Current column number [if this function was defined in a script]
*/
getColumnNumber(): number | null;

/**
* A call site object representing the location where eval was called
* [if this function was created using a call to eval]
*/
getEvalOrigin(): string | undefined;

/**
* Is this a toplevel invocation, that is, is "this" the global object?
*/
isToplevel(): boolean;

/**
* Does this call take place in code defined by a call to eval?
*/
isEval(): boolean;

/**
* Is this call in native V8 code?
*/
isNative(): boolean;

/**
* Is this a constructor call?
*/
isConstructor(): boolean;

getScriptNameOrSourceURL?(): string;
}

export function wrapCallSite(frame: CallSite, state?: State): CallSite;
export function getErrorSource(error: Error): string | null;
export function mapSourcePosition(position: Position): Position;
export function retrieveSourceMap(source: string): UrlAndMap | null;
export function resetRetrieveHandlers(): void;

/**
* Install SourceMap support.
* @param options Can be used to e.g. disable uncaughtException handler.
*/
export function install(options?: Options): void;
129 changes: 88 additions & 41 deletions types/source-map-support/source-map-support-tests.ts
Original file line number Diff line number Diff line change
@@ -1,36 +1,58 @@
import 'source-map-support/register';
import sms = require('source-map-support');
import * as sms from 'source-map-support';

sms.install();

function retrieveFile(path: string): string {
return 'foo';
}

function retrieveSourceMap(source: string): sms.UrlAndMap | null {
return source
? {
url: 'http://foo',
map: 'foo',
}
: null;
}

const options: sms.Options = {
emptyCacheBetweenOperations: false,
handleUncaughtExceptions: false,
retrieveFile,
retrieveSourceMap,
environment: 'node',
hookRequire: false,
overrideRetrieveSourceMap: false,
overrideRetrieveFile: false,
};

sms.install(options);
// test type exports
type UrlAndMap = sms.UrlAndMap;
type Environment = sms.Environment;
type Options = sms.Options;
type Position = sms.Position;
type State = sms.State;
type CallSite = sms.CallSite;

sms.install(); // $ExpectType void
sms.install({ handleUncaughtExceptions: false }); // $ExpectType void
sms.install({ hookRequire: false }); // $ExpectType void
sms.install({ emptyCacheBetweenOperations: true }); // $ExpectType void
sms.install({ environment: 'auto' }); // $ExpectType void
sms.install({ environment: 'browser' }); // $ExpectType void
sms.install({ environment: 'node' }); // $ExpectType void
// @ts-expect-error
sms.install({ environment: 'foo' });
sms.install({ overrideRetrieveFile: true }); // $ExpectType void
sms.install({ overrideRetrieveSourceMap: true }); // $ExpectType void
// $ExpectType void
sms.install({
retrieveFile: path => {
path; // $ExpectType string
return null;
},
});
sms.install({ retrieveFile: path => '' }); // $ExpectType void
// @ts-expect-error
sms.install({ retrieveFile: path => {} });
// $ExpectType void
sms.install({
retrieveSourceMap: source => {
source; // $ExpectType string
return null;
},
});
sms.install({ retrieveSourceMap: source => ({ map: 'foo' }) }); // $ExpectType void
// $ExpectType void
sms.install({
retrieveSourceMap: source => {
return {
map: {
mappings: '',
names: [''],
sources: [''],
version: '',
},
};
},
});
// $ExpectType void
sms.install({
...options,
retrieveSourceMap(source) {
return source
? {
Expand All @@ -47,21 +69,46 @@ sms.install({
: null;
},
});
// $ExpectType void
sms.install({
retrieveSourceMap: source => {
return {
map: 'foo',
url: 'foo',
};
},
});
// @ts-expect-error
sms.install({ retrieveSourceMap: source => 'foo' });

let stackFrame: any; // TODO: this should be a StackFrame, but it seems this would need to be defined elsewhere (in e.g. lib.d.ts)
stackFrame = sms.wrapCallSite(stackFrame);

let s: string | null;
s = sms.getErrorSource(new Error('foo'));

let p: sms.Position = {
declare const stackFrame: sms.CallSite;
const position: sms.Position = {
column: 0,
line: 0,
source: 'foo',
};
p = sms.mapSourcePosition(p);
sms.wrapCallSite(stackFrame); // $ExpectType CallSite
sms.wrapCallSite(stackFrame, { nextPosition: null, curPosition: null }); // $ExpectType CallSite
sms.wrapCallSite(stackFrame, { nextPosition: position, curPosition: null }); // $ExpectType CallSite
sms.wrapCallSite(stackFrame, { nextPosition: null, curPosition: position }); // $ExpectType CallSite
sms.getErrorSource(new Error('foo')); // $ExpectType string | null
// $ExpectType Position
sms.mapSourcePosition(position);
sms.resetRetrieveHandlers(); // $ExpectType void

let u: sms.UrlAndMap | null;
u = retrieveSourceMap('foo');

sms.resetRetrieveHandlers();
stackFrame.getThis(); // $ExpectType any
stackFrame.getTypeName(); // $ExpectType string | null
stackFrame.getFunction(); // $ExpectType ((...args: unknown[]) => any) | undefined
stackFrame.getFunctionName(); // $ExpectType string | null
stackFrame.getMethodName(); // $ExpectType string | null
stackFrame.getFileName(); // $ExpectType string | null
stackFrame.getLineNumber(); // $ExpectType number | null
stackFrame.getColumnNumber(); // $ExpectType number | null
stackFrame.getEvalOrigin(); // $ExpectType string | undefined
stackFrame.isToplevel(); // $ExpectType boolean
stackFrame.isEval(); // $ExpectType boolean
stackFrame.isNative(); // $ExpectType boolean
stackFrame.isConstructor(); // $ExpectType boolean
if (stackFrame.getScriptNameOrSourceURL) {
stackFrame.getScriptNameOrSourceURL(); // $ExpectType string
}