2020-12-14 13:13:08 +03:00
"use strict" ;
/ * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
* Copyright ( c ) Microsoft Corporation . All rights reserved .
* Licensed under the MIT License . See License . txt in the project root for license information .
* -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- * /
Object . defineProperty ( exports , "__esModule" , { value : true } ) ;
const ts = require ( "typescript" ) ;
const fs _1 = require ( "fs" ) ;
const path _1 = require ( "path" ) ;
const minimatch _1 = require ( "minimatch" ) ;
//
// #############################################################################################
//
// A custom typescript checker for the specific task of detecting the use of certain types in a
// layer that does not allow such use. For example:
// - using DOM globals in common/node/electron-main layer (e.g. HTMLElement)
// - using node.js globals in common/browser layer (e.g. process)
//
// Make changes to below RULES to lift certain files from these checks only if absolutely needed
//
// #############################################################################################
//
// Types we assume are present in all implementations of JS VMs (node.js, browsers)
// Feel free to add more core types as you see needed if present in node.js and browsers
const CORE _TYPES = [
2023-09-20 03:25:11 +03:00
'require' , // from our AMD loader
2020-12-14 13:13:08 +03:00
'setTimeout' ,
'clearTimeout' ,
'setInterval' ,
'clearInterval' ,
'console' ,
2022-04-04 16:04:29 +03:00
'Console' ,
2020-12-14 13:13:08 +03:00
'Error' ,
2022-04-04 16:04:29 +03:00
'ErrorConstructor' ,
2020-12-14 13:13:08 +03:00
'String' ,
'TextDecoder' ,
'TextEncoder' ,
'self' ,
2022-01-05 13:11:12 +03:00
'queueMicrotask' ,
2022-03-10 18:51:37 +03:00
'Array' ,
'Uint8Array' ,
'Uint16Array' ,
'Uint32Array' ,
'Int8Array' ,
'Int16Array' ,
'Int32Array' ,
'Float32Array' ,
'Float64Array' ,
'Uint8ClampedArray' ,
'BigUint64Array' ,
'BigInt64Array' ,
'btoa' ,
'atob' ,
2022-08-05 02:26:18 +03:00
'AbortController' ,
2022-03-10 18:51:37 +03:00
'AbortSignal' ,
2022-01-05 13:11:12 +03:00
'MessageChannel' ,
2022-04-04 12:21:57 +03:00
'MessagePort' ,
'URL' ,
2022-10-06 22:08:45 +03:00
'URLSearchParams' ,
'ReadonlyArray' ,
2023-08-07 15:46:27 +03:00
'Event' ,
'EventTarget' ,
'BroadcastChannel' ,
'performance' ,
2024-05-10 19:20:28 +03:00
'Blob' ,
'crypto' ,
'File' ,
'fetch' ,
'RequestInit' ,
'Headers' ,
2024-06-19 09:35:55 +03:00
'Response' ,
2024-07-31 01:37:27 +03:00
'__global' ,
'PerformanceMark' ,
'PerformanceObserver' ,
2024-08-30 11:31:46 +03:00
'ImportMeta'
2020-12-14 13:13:08 +03:00
] ;
// Types that are defined in a common layer but are known to be only
// available in native environments should not be allowed in browser
const NATIVE _TYPES = [
'NativeParsedArgs' ,
'INativeEnvironmentService' ,
2021-03-15 13:27:31 +03:00
'AbstractNativeEnvironmentService' ,
2020-12-14 13:13:08 +03:00
'INativeWindowConfiguration' ,
2023-02-25 17:49:47 +03:00
'ICommonNativeHostService' ,
'INativeHostService' ,
'IMainProcessService'
2020-12-14 13:13:08 +03:00
] ;
const RULES = [
// Tests: skip
{
target : '**/vs/**/test/**' ,
skip : true // -> skip all test files
} ,
// Common: vs/base/common/platform.ts
{
target : '**/vs/base/common/platform.ts' ,
allowedTypes : [
... CORE _TYPES ,
// Safe access to postMessage() and friends
'MessageEvent' ,
] ,
disallowedTypes : NATIVE _TYPES ,
disallowedDefinitions : [
2023-09-20 03:25:11 +03:00
'lib.dom.d.ts' , // no DOM
2020-12-14 13:13:08 +03:00
'@types/node' // no node.js
]
} ,
2023-11-07 14:52:20 +03:00
// Common: vs/base/common/async.ts
{
target : '**/vs/base/common/async.ts' ,
allowedTypes : [
... CORE _TYPES ,
// Safe access to requestIdleCallback & cancelIdleCallback
'requestIdleCallback' ,
'cancelIdleCallback'
] ,
disallowedTypes : NATIVE _TYPES ,
disallowedDefinitions : [
'lib.dom.d.ts' , // no DOM
'@types/node' // no node.js
]
} ,
2021-03-15 13:27:31 +03:00
// Common: vs/platform/environment/common/*
2020-12-14 13:13:08 +03:00
{
2021-03-15 13:27:31 +03:00
target : '**/vs/platform/environment/common/*.ts' ,
2020-12-14 13:13:08 +03:00
allowedTypes : CORE _TYPES ,
2022-02-08 22:09:00 +03:00
disallowedTypes : [ /* Ignore native types that are defined from here */ ] ,
2020-12-14 13:13:08 +03:00
disallowedDefinitions : [
2023-09-20 03:25:11 +03:00
'lib.dom.d.ts' , // no DOM
2020-12-14 13:13:08 +03:00
'@types/node' // no node.js
]
} ,
2022-02-14 10:41:24 +03:00
// Common: vs/platform/window/common/window.ts
2020-12-14 13:13:08 +03:00
{
2022-02-14 10:41:24 +03:00
target : '**/vs/platform/window/common/window.ts' ,
2020-12-14 13:13:08 +03:00
allowedTypes : CORE _TYPES ,
2022-02-08 22:09:00 +03:00
disallowedTypes : [ /* Ignore native types that are defined from here */ ] ,
2020-12-14 13:13:08 +03:00
disallowedDefinitions : [
2023-09-20 03:25:11 +03:00
'lib.dom.d.ts' , // no DOM
2020-12-14 13:13:08 +03:00
'@types/node' // no node.js
]
} ,
// Common: vs/platform/native/common/native.ts
{
target : '**/vs/platform/native/common/native.ts' ,
allowedTypes : CORE _TYPES ,
2022-02-08 22:09:00 +03:00
disallowedTypes : [ /* Ignore native types that are defined from here */ ] ,
2020-12-14 13:13:08 +03:00
disallowedDefinitions : [
2023-09-20 03:25:11 +03:00
'lib.dom.d.ts' , // no DOM
2020-12-14 13:13:08 +03:00
'@types/node' // no node.js
]
} ,
2023-11-06 14:00:24 +03:00
// Common: vs/platform/native/common/nativeHostService.ts
{
target : '**/vs/platform/native/common/nativeHostService.ts' ,
allowedTypes : CORE _TYPES ,
disallowedTypes : [ /* Ignore native types that are defined from here */ ] ,
disallowedDefinitions : [
'lib.dom.d.ts' , // no DOM
'@types/node' // no node.js
]
} ,
2020-12-14 13:13:08 +03:00
// Common: vs/workbench/api/common/extHostExtensionService.ts
{
target : '**/vs/workbench/api/common/extHostExtensionService.ts' ,
allowedTypes : [
... CORE _TYPES ,
// Safe access to global
'global'
] ,
disallowedTypes : NATIVE _TYPES ,
disallowedDefinitions : [
2023-09-20 03:25:11 +03:00
'lib.dom.d.ts' , // no DOM
2020-12-14 13:13:08 +03:00
'@types/node' // no node.js
]
} ,
2024-06-19 09:35:55 +03:00
// Common: vs/base/parts/sandbox/electron-sandbox/preload.js
2024-05-10 19:20:28 +03:00
{
2024-06-19 09:35:55 +03:00
target : '**/vs/base/parts/sandbox/electron-sandbox/preload.js' ,
2024-05-10 19:20:28 +03:00
allowedTypes : [
... CORE _TYPES ,
2024-06-19 09:35:55 +03:00
// Safe access to a very small subset of node.js
'process' ,
'NodeJS'
2024-05-10 19:20:28 +03:00
] ,
disallowedTypes : NATIVE _TYPES ,
disallowedDefinitions : [
'@types/node' // no node.js
]
} ,
2020-12-14 13:13:08 +03:00
// Common
{
target : '**/vs/**/common/**' ,
allowedTypes : CORE _TYPES ,
disallowedTypes : NATIVE _TYPES ,
disallowedDefinitions : [
2023-09-20 03:25:11 +03:00
'lib.dom.d.ts' , // no DOM
2020-12-14 13:13:08 +03:00
'@types/node' // no node.js
]
} ,
// Browser
{
target : '**/vs/**/browser/**' ,
allowedTypes : CORE _TYPES ,
disallowedTypes : NATIVE _TYPES ,
2022-03-10 18:51:37 +03:00
allowedDefinitions : [
'@types/node/stream/consumers.d.ts' // node.js started to duplicate types from lib.dom.d.ts so we have to account for that
] ,
2020-12-14 13:13:08 +03:00
disallowedDefinitions : [
'@types/node' // no node.js
]
} ,
// Browser (editor contrib)
{
target : '**/src/vs/editor/contrib/**' ,
allowedTypes : CORE _TYPES ,
disallowedTypes : NATIVE _TYPES ,
disallowedDefinitions : [
'@types/node' // no node.js
]
} ,
// node.js
{
target : '**/vs/**/node/**' ,
2022-04-04 16:04:29 +03:00
allowedTypes : CORE _TYPES ,
2020-12-14 13:13:08 +03:00
disallowedDefinitions : [
'lib.dom.d.ts' // no DOM
]
} ,
// Electron (sandbox)
{
target : '**/vs/**/electron-sandbox/**' ,
allowedTypes : CORE _TYPES ,
disallowedDefinitions : [
'@types/node' // no node.js
]
} ,
2024-09-05 10:49:23 +03:00
// Electron (utility)
2024-09-04 17:26:43 +03:00
{
2024-09-05 10:49:23 +03:00
target : '**/vs/**/electron-utility/**' ,
2024-09-04 17:26:43 +03:00
allowedTypes : [
... CORE _TYPES ,
// --> types from electron.d.ts that duplicate from lib.dom.d.ts
'Event' ,
'Request'
] ,
disallowedTypes : [
'ipcMain' // not allowed, use validatedIpcMain instead
] ,
disallowedDefinitions : [
'lib.dom.d.ts' // no DOM
]
} ,
2020-12-14 13:13:08 +03:00
// Electron (main)
{
target : '**/vs/**/electron-main/**' ,
allowedTypes : [
... CORE _TYPES ,
// --> types from electron.d.ts that duplicate from lib.dom.d.ts
'Event' ,
'Request'
] ,
2022-04-12 08:46:17 +03:00
disallowedTypes : [
'ipcMain' // not allowed, use validatedIpcMain instead
] ,
2020-12-14 13:13:08 +03:00
disallowedDefinitions : [
'lib.dom.d.ts' // no DOM
]
}
] ;
2021-07-09 00:27:39 +03:00
const TS _CONFIG _PATH = ( 0 , path _1 . join ) ( _ _dirname , '../../' , 'src' , 'tsconfig.json' ) ;
2020-12-14 13:13:08 +03:00
let hasErrors = false ;
function checkFile ( program , sourceFile , rule ) {
checkNode ( sourceFile ) ;
function checkNode ( node ) {
if ( node . kind !== ts . SyntaxKind . Identifier ) {
return ts . forEachChild ( node , checkNode ) ; // recurse down
}
2022-04-04 16:04:29 +03:00
const checker = program . getTypeChecker ( ) ;
const symbol = checker . getSymbolAtLocation ( node ) ;
if ( ! symbol ) {
return ;
}
let _parentSymbol = symbol ;
while ( _parentSymbol . parent ) {
_parentSymbol = _parentSymbol . parent ;
}
const parentSymbol = _parentSymbol ;
const text = parentSymbol . getName ( ) ;
2022-03-01 01:00:17 +03:00
if ( rule . allowedTypes ? . some ( allowed => allowed === text ) ) {
2020-12-14 13:13:08 +03:00
return ; // override
}
2022-03-01 01:00:17 +03:00
if ( rule . disallowedTypes ? . some ( disallowed => disallowed === text ) ) {
2020-12-14 13:13:08 +03:00
const { line , character } = sourceFile . getLineAndCharacterOfPosition ( node . getStart ( ) ) ;
2022-08-10 16:37:21 +03:00
console . log ( ` [build/lib/layersChecker.ts]: Reference to type ' ${ text } ' violates layer ' ${ rule . target } ' ( ${ sourceFile . fileName } ( ${ line + 1 } , ${ character + 1 } ). Learn more about our source code organization at https://github.com/microsoft/vscode/wiki/Source-Code-Organization. ` ) ;
2020-12-14 13:13:08 +03:00
hasErrors = true ;
return ;
}
2022-04-04 16:04:29 +03:00
const declarations = symbol . declarations ;
if ( Array . isArray ( declarations ) ) {
DeclarationLoop : for ( const declaration of declarations ) {
if ( declaration ) {
const parent = declaration . parent ;
if ( parent ) {
const parentSourceFile = parent . getSourceFile ( ) ;
if ( parentSourceFile ) {
const definitionFileName = parentSourceFile . fileName ;
if ( rule . allowedDefinitions ) {
for ( const allowedDefinition of rule . allowedDefinitions ) {
if ( definitionFileName . indexOf ( allowedDefinition ) >= 0 ) {
continue DeclarationLoop ;
2022-02-08 22:09:00 +03:00
}
}
2022-04-04 16:04:29 +03:00
}
if ( rule . disallowedDefinitions ) {
for ( const disallowedDefinition of rule . disallowedDefinitions ) {
if ( definitionFileName . indexOf ( disallowedDefinition ) >= 0 ) {
const { line , character } = sourceFile . getLineAndCharacterOfPosition ( node . getStart ( ) ) ;
2022-08-10 16:37:21 +03:00
console . log ( ` [build/lib/layersChecker.ts]: Reference to symbol ' ${ text } ' from ' ${ disallowedDefinition } ' violates layer ' ${ rule . target } ' ( ${ sourceFile . fileName } ( ${ line + 1 } , ${ character + 1 } ) Learn more about our source code organization at https://github.com/microsoft/vscode/wiki/Source-Code-Organization. ` ) ;
2022-04-04 16:04:29 +03:00
hasErrors = true ;
return ;
2020-12-14 13:13:08 +03:00
}
}
}
}
}
}
}
}
}
}
function createProgram ( tsconfigPath ) {
const tsConfig = ts . readConfigFile ( tsconfigPath , ts . sys . readFile ) ;
2021-07-09 00:27:39 +03:00
const configHostParser = { fileExists : fs _1 . existsSync , readDirectory : ts . sys . readDirectory , readFile : file => ( 0 , fs _1 . readFileSync ) ( file , 'utf8' ) , useCaseSensitiveFileNames : process . platform === 'linux' } ;
const tsConfigParsed = ts . parseJsonConfigFileContent ( tsConfig . config , configHostParser , ( 0 , path _1 . resolve ) ( ( 0 , path _1 . dirname ) ( tsconfigPath ) ) , { noEmit : true } ) ;
2020-12-14 13:13:08 +03:00
const compilerHost = ts . createCompilerHost ( tsConfigParsed . options , true ) ;
return ts . createProgram ( tsConfigParsed . fileNames , tsConfigParsed . options , compilerHost ) ;
}
//
// Create program and start checking
//
const program = createProgram ( TS _CONFIG _PATH ) ;
for ( const sourceFile of program . getSourceFiles ( ) ) {
for ( const rule of RULES ) {
2021-07-09 00:27:39 +03:00
if ( ( 0 , minimatch _1 . match ) ( [ sourceFile . fileName ] , rule . target ) . length > 0 ) {
2020-12-14 13:13:08 +03:00
if ( ! rule . skip ) {
checkFile ( program , sourceFile , rule ) ;
}
break ;
}
}
}
if ( hasErrors ) {
process . exit ( 1 ) ;
}
2023-11-22 16:05:46 +03:00
//# sourceMappingURL=layersChecker.js.map