From f40a55fc313fac5973de5c777aa431b0f9c809eb Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 10 Mar 2021 15:09:26 +0100 Subject: [PATCH 1/7] Add SECURITY.md --- SECURITY.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) create mode 100644 SECURITY.md diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 00000000..10541931 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,41 @@ + + +## Security + +Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/Microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/). + +If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](), please report it to us as described below. + +## Reporting Security Issues + +**Please do not report security vulnerabilities through public GitHub issues.** + +Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://msrc.microsoft.com/create-report). + +If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://www.microsoft.com/en-us/msrc/pgp-key-msrc). + +You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://www.microsoft.com/msrc). + +Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue: + +- Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.) +- Full paths of source file(s) related to the manifestation of the issue +- The location of the affected source code (tag/branch/commit or direct URL) +- Any special configuration required to reproduce the issue +- Step-by-step instructions to reproduce the issue +- Proof-of-concept or exploit code (if possible) +- Impact of the issue, including how an attacker might exploit the issue + +This information will help us triage your report more quickly. + +If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://microsoft.com/msrc/bounty) page for more details about our active programs. + +## Preferred Languages + +We prefer all communications to be in English. + +## Policy + +Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://www.microsoft.com/en-us/msrc/cvd). + + From 19071cd8fa1e406b4361c53b3eacd3c9ff2fd37a Mon Sep 17 00:00:00 2001 From: Sebastian Pahnke Date: Wed, 17 Mar 2021 12:58:05 +0100 Subject: [PATCH 2/7] Deep clone diagnostic objects Fixes https://github.com/microsoft/monaco-editor/issues/2392 --- src/tsWorker.ts | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/tsWorker.ts b/src/tsWorker.ts index be58d05f..dcab44c6 100644 --- a/src/tsWorker.ts +++ b/src/tsWorker.ts @@ -8,6 +8,7 @@ import * as ts from './lib/typescriptServices'; import { libFileMap } from './lib/lib'; import { Diagnostic, + DiagnosticRelatedInformation, IExtraLibs, TypeScriptWorker as ITypeScriptWorker } from './monaco.contribution'; @@ -177,17 +178,26 @@ export class TypeScriptWorker implements ts.LanguageServiceHost, ITypeScriptWork // --- language features - private static clearFiles(diagnostics: ts.Diagnostic[]): Diagnostic[] { + private static clearFiles(tsDiagnostics: ts.Diagnostic[]): Diagnostic[] { // Clear the `file` field, which cannot be JSON'yfied because it // contains cyclic data structures, except for the `fileName` // property. - diagnostics.forEach((diag: Diagnostic) => { - diag.file = diag.file ? { fileName: diag.file.fileName } : undefined; - diag.relatedInformation?.forEach( - (diag2) => (diag2.file = diag2.file ? { fileName: diag2.file.fileName } : undefined) - ); - }); - return diagnostics; + // Do a deep clone so we don't mutate the ts.Diagnostic object (see https://github.com/microsoft/monaco-editor/issues/2392) + const diagnostics: Diagnostic[] = []; + for (const tsDiagnostic of tsDiagnostics) { + const diagnostic: Diagnostic = { ...tsDiagnostic }; + diagnostic.file = diagnostic.file ? { fileName: diagnostic.file.fileName } : undefined; + if (tsDiagnostic.relatedInformation) { + diagnostic.relatedInformation = []; + for (const tsRelatedDiagnostic of tsDiagnostic.relatedInformation) { + const relatedDiagnostic: DiagnosticRelatedInformation = { ...tsRelatedDiagnostic }; + relatedDiagnostic.file = relatedDiagnostic.file ? { fileName: relatedDiagnostic.file.fileName } : undefined + diagnostic.relatedInformation.push(relatedDiagnostic); + } + } + diagnostics.push(diagnostic); + } + return diagnostics; } async getSyntacticDiagnostics(fileName: string): Promise { From 22e7676a8c05c95ff451fe2306bebf5ed2421b4d Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Tue, 11 May 2021 14:27:47 +0200 Subject: [PATCH 3/7] Add `DiagnosticsOptions.onlyVisible` to limit computing diagnostics to only the visible text models --- monaco.d.ts | 5 ++++ src/languageFeatures.ts | 50 ++++++++++++++++++++++++++++++++------ src/monaco.contribution.ts | 5 ++-- 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/monaco.d.ts b/monaco.d.ts index feb49fc4..1021c98f 100644 --- a/monaco.d.ts +++ b/monaco.d.ts @@ -143,6 +143,11 @@ declare namespace monaco.languages.typescript { noSemanticValidation?: boolean; noSyntaxValidation?: boolean; noSuggestionDiagnostics?: boolean; + /** + * Limit diagnostic computation to only visible files. + * Defaults to false. + */ + onlyVisible?: boolean; diagnosticCodesToIgnore?: number[]; } export interface WorkerOptions { diff --git a/src/languageFeatures.ts b/src/languageFeatures.ts index abf50136..d54c7a1a 100644 --- a/src/languageFeatures.ts +++ b/src/languageFeatures.ts @@ -163,6 +163,15 @@ enum DiagnosticCategory { Message = 3 } +/** + * temporary interface until the editor API exposes + * `IModel.isAttachedToEditor` and `IModel.onDidChangeAttached` + */ +interface IInternalEditorModel extends editor.IModel { + onDidChangeAttached(listener: () => void): IDisposable; + isAttachedToEditor(): boolean; +} + export class DiagnosticsAdapter extends Adapter { private _disposables: IDisposable[] = []; private _listener: { [uri: string]: IDisposable } = Object.create(null); @@ -175,25 +184,52 @@ export class DiagnosticsAdapter extends Adapter { ) { super(worker); - const onModelAdd = (model: editor.IModel): void => { + const onModelAdd = (model: IInternalEditorModel): void => { if (model.getModeId() !== _selector) { return; } + const maybeValidate = () => { + const { onlyVisible } = this._defaults.getDiagnosticsOptions(); + if (onlyVisible) { + if (model.isAttachedToEditor()) { + this._doValidate(model); + } + } else { + this._doValidate(model); + } + }; + let handle: number; const changeSubscription = model.onDidChangeContent(() => { clearTimeout(handle); - handle = setTimeout(() => this._doValidate(model), 500); + handle = setTimeout(maybeValidate, 500); + }); + + const visibleSubscription = model.onDidChangeAttached(() => { + const { onlyVisible } = this._defaults.getDiagnosticsOptions(); + if (onlyVisible) { + if (model.isAttachedToEditor()) { + // this model is now attached to an editor + // => compute diagnostics + maybeValidate(); + } else { + // this model is no longer attached to an editor + // => clear existing diagnostics + editor.setModelMarkers(model, this._selector, []); + } + } }); this._listener[model.uri.toString()] = { dispose() { changeSubscription.dispose(); + visibleSubscription.dispose(); clearTimeout(handle); } }; - this._doValidate(model); + maybeValidate(); }; const onModelRemoved = (model: editor.IModel): void => { @@ -205,12 +241,12 @@ export class DiagnosticsAdapter extends Adapter { } }; - this._disposables.push(editor.onDidCreateModel(onModelAdd)); + this._disposables.push(editor.onDidCreateModel((model) => onModelAdd(model))); this._disposables.push(editor.onWillDisposeModel(onModelRemoved)); this._disposables.push( editor.onDidChangeModelLanguage((event) => { onModelRemoved(event.model); - onModelAdd(event.model); + onModelAdd(event.model); }) ); @@ -226,13 +262,13 @@ export class DiagnosticsAdapter extends Adapter { // redo diagnostics when options change for (const model of editor.getModels()) { onModelRemoved(model); - onModelAdd(model); + onModelAdd(model); } }; this._disposables.push(this._defaults.onDidChange(recomputeDiagostics)); this._disposables.push(this._defaults.onDidExtraLibsChange(recomputeDiagostics)); - editor.getModels().forEach(onModelAdd); + editor.getModels().forEach((model) => onModelAdd(model)); } public dispose(): void { diff --git a/src/monaco.contribution.ts b/src/monaco.contribution.ts index 534676f3..d1f0ea3c 100644 --- a/src/monaco.contribution.ts +++ b/src/monaco.contribution.ts @@ -156,6 +156,7 @@ export interface DiagnosticsOptions { noSemanticValidation?: boolean; noSyntaxValidation?: boolean; noSuggestionDiagnostics?: boolean; + onlyVisible?: boolean; diagnosticCodesToIgnore?: number[]; } @@ -616,13 +617,13 @@ export const typescriptVersion: string = tsversion; export const typescriptDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( { allowNonTsExtensions: true, target: ScriptTarget.Latest }, - { noSemanticValidation: false, noSyntaxValidation: false }, + { noSemanticValidation: false, noSyntaxValidation: false, onlyVisible: false }, {} ); export const javascriptDefaults: LanguageServiceDefaults = new LanguageServiceDefaultsImpl( { allowNonTsExtensions: true, allowJs: true, target: ScriptTarget.Latest }, - { noSemanticValidation: true, noSyntaxValidation: false }, + { noSemanticValidation: true, noSyntaxValidation: false, onlyVisible: false }, {} ); From 9084b555717a7b875ab21597fb49249ce5d8554e Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 17:58:44 +0200 Subject: [PATCH 4/7] Update `typescript` --- package-lock.json | 6 +++--- package.json | 2 +- src/lib/typescriptServices-amd.js | 24 ++++++++++++------------ src/lib/typescriptServices.js | 24 ++++++++++++------------ src/lib/typescriptServicesMetadata.ts | 2 +- src/monaco.contribution.ts | 4 ++++ 6 files changed, 33 insertions(+), 29 deletions(-) diff --git a/package-lock.json b/package-lock.json index 0d7bbb0e..eca63da5 100644 --- a/package-lock.json +++ b/package-lock.json @@ -461,9 +461,9 @@ } }, "typescript": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.3.tgz", - "integrity": "sha512-qOcYwxaByStAWrBf4x0fibwZvMRG+r4cQoTjbPtUlrWjBHbmCAww1i448U0GJ+3cNNEtebDteo/cHOR3xJ4wEw==", + "version": "4.2.4", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.2.4.tgz", + "integrity": "sha512-V+evlYHZnQkaz8TRBuxTA92yZBPotr5H+WhQ7bD3hZUndx5tGOa1fuCgeSjxAzM1RiN5IzvadIXTVefuuwZCRg==", "dev": true }, "which": { diff --git a/package.json b/package.json index 68d17411..8a9aa137 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "pretty-quick": "^3.1.0", "requirejs": "^2.3.6", "terser": "^5.6.0", - "typescript": "^4.2.3" + "typescript": "^4.2.4" }, "husky": { "hooks": { diff --git a/src/lib/typescriptServices-amd.js b/src/lib/typescriptServices-amd.js index 4e113ea5..af79b3e1 100644 --- a/src/lib/typescriptServices-amd.js +++ b/src/lib/typescriptServices-amd.js @@ -293,7 +293,7 @@ var ts; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types - ts.version = "4.2.3"; + ts.version = "4.2.4"; /* @internal */ var Comparison; (function (Comparison) { @@ -46611,7 +46611,9 @@ var ts; var result = new Type(checker, flags); typeCount++; result.id = typeCount; - typeCatalog.push(result); + if (ts.tracing) { + typeCatalog.push(result); + } return result; } function createOriginType(flags) { @@ -148422,7 +148424,7 @@ var ts; }; SignatureObject.prototype.getJsDocTags = function () { if (this.jsDocTags === undefined) { - this.jsDocTags = this.declaration ? getJsDocTags([this.declaration], this.checker) : []; + this.jsDocTags = this.declaration ? getJsDocTagsOfSignature(this.declaration, this.checker) : []; } return this.jsDocTags; }; @@ -148436,15 +148438,13 @@ var ts; function hasJSDocInheritDocTag(node) { return ts.getJSDocTags(node).some(function (tag) { return tag.tagName.text === "inheritDoc"; }); } - function getJsDocTags(declarations, checker) { - var tags = ts.JsDoc.getJsDocTagsFromDeclarations(declarations); - if (tags.length === 0 || declarations.some(hasJSDocInheritDocTag)) { - ts.forEachUnique(declarations, function (declaration) { - var inheritedTags = findBaseOfDeclaration(checker, declaration, function (symbol) { return symbol.getJsDocTags(); }); - if (inheritedTags) { - tags = __spreadArray(__spreadArray([], inheritedTags), tags); - } - }); + function getJsDocTagsOfSignature(declaration, checker) { + var tags = ts.JsDoc.getJsDocTagsFromDeclarations([declaration]); + if (tags.length === 0 || hasJSDocInheritDocTag(declaration)) { + var inheritedTags = findBaseOfDeclaration(checker, declaration, function (symbol) { var _a; return ((_a = symbol.declarations) === null || _a === void 0 ? void 0 : _a.length) === 1 ? symbol.getJsDocTags() : undefined; }); + if (inheritedTags) { + tags = __spreadArray(__spreadArray([], inheritedTags), tags); + } } return tags; } diff --git a/src/lib/typescriptServices.js b/src/lib/typescriptServices.js index 6142d712..0e7de0f2 100644 --- a/src/lib/typescriptServices.js +++ b/src/lib/typescriptServices.js @@ -293,7 +293,7 @@ var ts; // The following is baselined as a literal template type without intervention /** The version of the TypeScript compiler release */ // eslint-disable-next-line @typescript-eslint/no-inferrable-types - ts.version = "4.2.3"; + ts.version = "4.2.4"; /* @internal */ var Comparison; (function (Comparison) { @@ -46611,7 +46611,9 @@ var ts; var result = new Type(checker, flags); typeCount++; result.id = typeCount; - typeCatalog.push(result); + if (ts.tracing) { + typeCatalog.push(result); + } return result; } function createOriginType(flags) { @@ -148422,7 +148424,7 @@ var ts; }; SignatureObject.prototype.getJsDocTags = function () { if (this.jsDocTags === undefined) { - this.jsDocTags = this.declaration ? getJsDocTags([this.declaration], this.checker) : []; + this.jsDocTags = this.declaration ? getJsDocTagsOfSignature(this.declaration, this.checker) : []; } return this.jsDocTags; }; @@ -148436,15 +148438,13 @@ var ts; function hasJSDocInheritDocTag(node) { return ts.getJSDocTags(node).some(function (tag) { return tag.tagName.text === "inheritDoc"; }); } - function getJsDocTags(declarations, checker) { - var tags = ts.JsDoc.getJsDocTagsFromDeclarations(declarations); - if (tags.length === 0 || declarations.some(hasJSDocInheritDocTag)) { - ts.forEachUnique(declarations, function (declaration) { - var inheritedTags = findBaseOfDeclaration(checker, declaration, function (symbol) { return symbol.getJsDocTags(); }); - if (inheritedTags) { - tags = __spreadArray(__spreadArray([], inheritedTags), tags); - } - }); + function getJsDocTagsOfSignature(declaration, checker) { + var tags = ts.JsDoc.getJsDocTagsFromDeclarations([declaration]); + if (tags.length === 0 || hasJSDocInheritDocTag(declaration)) { + var inheritedTags = findBaseOfDeclaration(checker, declaration, function (symbol) { var _a; return ((_a = symbol.declarations) === null || _a === void 0 ? void 0 : _a.length) === 1 ? symbol.getJsDocTags() : undefined; }); + if (inheritedTags) { + tags = __spreadArray(__spreadArray([], inheritedTags), tags); + } } return tags; } diff --git a/src/lib/typescriptServicesMetadata.ts b/src/lib/typescriptServicesMetadata.ts index f8dc83a7..01ba296c 100644 --- a/src/lib/typescriptServicesMetadata.ts +++ b/src/lib/typescriptServicesMetadata.ts @@ -2,4 +2,4 @@ // **NOTE**: Do not edit directly! This file is generated using `npm run import-typescript` // -export const typescriptVersion = "4.2.3"; +export const typescriptVersion = "4.2.4"; diff --git a/src/monaco.contribution.ts b/src/monaco.contribution.ts index d1f0ea3c..a2f8984d 100644 --- a/src/monaco.contribution.ts +++ b/src/monaco.contribution.ts @@ -156,6 +156,10 @@ export interface DiagnosticsOptions { noSemanticValidation?: boolean; noSyntaxValidation?: boolean; noSuggestionDiagnostics?: boolean; + /** + * Limit diagnostic computation to only visible files. + * Defaults to false. + */ onlyVisible?: boolean; diagnosticCodesToIgnore?: number[]; } From 50ead0342b36e1a6917c197014aeec7cd92116a2 Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 17:59:37 +0200 Subject: [PATCH 5/7] Adopt latest `monaco-editor-core` --- package-lock.json | 12 ++++++------ package.json | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/package-lock.json b/package-lock.json index eca63da5..1c2635a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -237,15 +237,15 @@ } }, "monaco-editor-core": { - "version": "0.23.0", - "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.23.0.tgz", - "integrity": "sha512-1LHVpCHp+FErFdUjwzal1muTe+hUkR5CfXAxzua//eHB31bHdWVe15OJPEPS3/rxmfQtl9wZqJdHi4FcGz2zog==", + "version": "0.24.0", + "resolved": "https://registry.npmjs.org/monaco-editor-core/-/monaco-editor-core-0.24.0.tgz", + "integrity": "sha512-WJAzpNYEaJp8Z7crIAiLCVln1zZdo4cFXCRuhTDN4A3tz6IK2NOXAtTOZ9iLKBTtd6eitZJ2Q1Fx8JN8rN3fWw==", "dev": true }, "monaco-languages": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-2.3.0.tgz", - "integrity": "sha512-gER/vKpIUH2kKhWEWRDojMuI6cm4S7Dl9jSYNFUfToOB8uIxoWSZUJCm2FH+ECnUZmnLs6O2fNONKQQ6JCoa/g==", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/monaco-languages/-/monaco-languages-2.4.0.tgz", + "integrity": "sha512-63ZMAPgqBylS0kyC22QSKJWJmCRcwM7dWql1xtt9R7mCfzszfIIViSTiJ5vDSnzj0lH0aZh8OJggh/uZY6Vgnw==", "dev": true }, "monaco-plugin-helpers": { diff --git a/package.json b/package.json index 8a9aa137..d2dd4a7e 100644 --- a/package.json +++ b/package.json @@ -25,8 +25,8 @@ "devDependencies": { "@typescript/vfs": "^1.3.4", "husky": "^5.1.3", - "monaco-editor-core": "^0.23.0", - "monaco-languages": "^2.3.0", + "monaco-editor-core": "^0.24.0", + "monaco-languages": "^2.4.0", "monaco-plugin-helpers": "^1.0.3", "prettier": "^2.2.1", "pretty-quick": "^3.1.0", From e7d5b97033b3a498bd58612f957bc03ce06006cf Mon Sep 17 00:00:00 2001 From: Alex Dima Date: Wed, 12 May 2021 18:01:43 +0200 Subject: [PATCH 6/7] 4.4.0 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 1c2635a8..0d06b3f3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "monaco-typescript", - "version": "4.3.1", + "version": "4.4.0", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d2dd4a7e..3f423146 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "monaco-typescript", - "version": "4.3.1", + "version": "4.4.0", "description": "TypeScript and JavaScript language support for Monaco Editor", "scripts": { "compile-amd": "mcopy ./src/lib/typescriptServices-amd.js ./out/amd/lib/typescriptServices.js && tsc -p ./src/tsconfig.json", From e0c11b34f5f1962fa92c8aff02dbde98d072b412 Mon Sep 17 00:00:00 2001 From: paranoidjk Date: Fri, 14 May 2021 21:40:44 +0800 Subject: [PATCH 7/7] fix: support go to definition for extraLib file --- src/languageFeatures.ts | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/src/languageFeatures.ts b/src/languageFeatures.ts index d54c7a1a..e7fe97a9 100644 --- a/src/languageFeatures.ts +++ b/src/languageFeatures.ts @@ -7,7 +7,8 @@ import { Diagnostic, DiagnosticRelatedInformation, - LanguageServiceDefaults + LanguageServiceDefaults, + typescriptDefaults } from './monaco.contribution'; import type * as ts from './lib/typescriptServices'; import type { TypeScriptWorker } from './tsWorker'; @@ -789,6 +790,17 @@ export class DefinitionAdapter extends Adapter { uri: uri, range: this._textSpanToRange(refModel, entry.textSpan) }); + } else { + const matchedLibFile = typescriptDefaults.getExtraLibs()[entry.fileName] + if (matchedLibFile) { + const libModel = editor.createModel(matchedLibFile.content, 'typescript', uri); + return { + uri: uri, + range: this._textSpanToRange(libModel, entry.textSpan) + } + } + + } } return result;