deno_lint
deno_lint copied to clipboard
Automate acquisition of global properties
#419 was just fixed by #421, adding AggregateError
to the globals list: https://github.com/denoland/deno_lint/blob/master/src/globals.rs
However, I noticed that there are some other inconsistencies between that list and what is produced by enumerating the list in Deno:
const caseInsensitiveSort = (a: string, b: string): number => {
const lowerA = a.toLowerCase();
const lowerB = b.toLowerCase();
if (lowerA < lowerB) return -1;
if (lowerA > lowerB) return 1;
return 0;
};
const globals = [...Object.getOwnPropertyNames(globalThis)];
console.log(globals.sort(caseInsensitiveSort).join('\n'));
Which produces this list in Deno 1.4.6
:
AbortController
AbortSignal
addEventListener
AggregateError
Array
ArrayBuffer
atob
Atomics
BigInt
BigInt64Array
BigUint64Array
Blob
Boolean
btoa
ByteLengthQueuingStrategy
clearInterval
clearTimeout
close
closed
CloseEvent
console
CountQueuingStrategy
crypto
CustomEvent
DataView
Date
decodeURI
decodeURIComponent
Deno
dispatchEvent
DOMException
encodeURI
encodeURIComponent
Error
ErrorEvent
escape
eval
EvalError
Event
EventTarget
fetch
File
FileReader
FinalizationRegistry
Float32Array
Float64Array
FormData
Function
globalThis
Headers
Infinity
Int16Array
Int32Array
Int8Array
isFinite
isNaN
JSON
Map
Math
MessageEvent
NaN
Number
Object
onload
onunload
parseFloat
parseInt
Performance
performance
PerformanceEntry
PerformanceMark
PerformanceMeasure
ProgressEvent
Promise
Proxy
queueMicrotask
RangeError
ReadableStream
ReferenceError
Reflect
RegExp
removeEventListener
Request
Response
self
Set
setInterval
setTimeout
SharedArrayBuffer
String
Symbol
SyntaxError
TextDecoder
TextEncoder
TransformStream
TypeError
Uint16Array
Uint32Array
Uint8Array
Uint8ClampedArray
undefined
unescape
URIError
URL
URLSearchParams
WeakMap
WeakRef
WeakSet
WebAssembly
WebSocket
window
Worker
WritableStream
How is src/globals.rs
being maintained? Is it a manual process? Can it be automated?
@jsejcksn thanks for the report, it is indeed a problem. I did an update to the list based on your findings in https://github.com/denoland/deno_lint/pull/426. Unfortunately I see no clear way to automate this process at the moment, so I'm gonna keep the issue open
@bartlomieju I see there are some entries in globals.rs
which are not produced using the method above. I tried to access a couple of them and got undefined
. Where are they coming from / why are they in the list?
@jsejcksn could you list those? I've checked the list when I added it originally so I'm a bit surprised something is undefined
.
@bartlomieju See item 3 below. Here's a script that will
- fetch the current source and save to
./globals-src.rs
- create an updated source from the computed globals and save to
./globals-computed.rs
- parse each list and log the types associated to the exclusive values (see output)
globals.ts
:
// deno run --allow-net="raw.githubusercontent.com" --allow-read="globals-computed.rs","globals-src.rs" --allow-write="globals-computed.rs","globals-src.rs" globals.ts
const indent = ' ';
const newline = '\n';
const computedPath = 'globals-computed.rs';
const srcPath = 'globals-src.rs';
const srcPreList = `// Copyright 2020 the Deno authors. All rights reserved. MIT license.
/// List of globals available in Deno environment
///
/// Adapted from https://www.npmjs.com/package/globals
#[allow(unused)]
pub static GLOBALS: &[&str] = &[${newline}`;
const srcPostList = `];${newline}`;
const fetchSource = async (): Promise<string> => {
const url = 'https://raw.githubusercontent.com/denoland/deno_lint/master/src/globals.rs';
const response = await fetch(url);
if (!response.ok) throw new Error('Response not OK');
return response.text();
};
const caseInsensitiveSort = (a: string, b: string): number => {
const lowerA = a.toLowerCase();
const lowerB = b.toLowerCase();
if (lowerA < lowerB) return -1;
if (lowerA > lowerB) return 1;
return 0;
};
const getComputedGlobals = (): string[] => {
const globals = [...Object.getOwnPropertyNames(globalThis)];
return globals.sort(caseInsensitiveSort);
};
const updateSourceFiles = async () => {
const globals = getComputedGlobals();
const listReducer = (
string: string,
value: string,
) => `${string}${indent}"${value}",${newline}`;
const list = globals.reduce(listReducer, '');
const result = `${srcPreList}${list}${srcPostList}`;
await Deno.writeTextFile(computedPath, result);
const src = await fetchSource();
await Deno.writeTextFile(srcPath, src);
};
const parseGlobalsFromSource = async (src: string): Promise<string[]> => {
const listItemRegex = / {2}"\w+",/gu;
const globals = (await Deno.readTextFile(src))
.match(listItemRegex)
?.map(str => str.slice(3, -2)) ?? [];
return globals;
};
const main = async () => {
await updateSourceFiles();
const srcGlobals = new Set(await parseGlobalsFromSource(srcPath));
const computedGlobals = new Set(await parseGlobalsFromSource(computedPath));
const commonGlobals = new Set<string>();
for (const value of srcGlobals.values()) {
if (computedGlobals.has(value)) commonGlobals.add(value);
}
for (const value of commonGlobals.values()) {
computedGlobals.delete(value);
srcGlobals.delete(value);
}
const listReducer = (
string: string,
value: string,
// deno-lint-ignore no-explicit-any
) => `${string}${indent}${value}: ${typeof (globalThis as any)[value]}${newline}`;
console.log(`Exclusive computed:${newline}${[...computedGlobals.values()]
.reduce(listReducer, '')}`);
console.log(`Exclusive source:${newline}${[...srcGlobals.values()]
.reduce(listReducer, '')}`);
};
if (import.meta.main) main();
output:
Exclusive computed:
ByteLengthQueuingStrategy: function
MessageEvent: function
onload: object
onunload: object
Exclusive source:
constructor: function
event: undefined
EventSource: undefined
hasOwnProperty: function
isPrototypeOf: function
onmessage: undefined
onmessageerror: undefined
Permissions: undefined
PermissionStatus: undefined
postMessage: undefined
propertyIsEnumerable: function
toLocaleString: function
toString: function
valueOf: function
Window: undefined