@@ -24,51 +24,16 @@ export type Options = [Config];
2424export type MessageIds = 'unbound' | 'unboundWithoutThisAnnotation' ;
2525
2626/**
27- * The following is a list of exceptions to the rule
28- * Generated via the following script.
29- * This is statically defined to save making purposely invalid calls every lint run
30- * ```
31- SUPPORTED_GLOBALS.flatMap(namespace => {
32- const object = window[namespace];
33- return Object.getOwnPropertyNames(object)
34- .filter(
35- name =>
36- !name.startsWith('_') &&
37- typeof object[name] === 'function',
38- )
39- .map(name => {
40- try {
41- const x = object[name];
42- x();
43- } catch (e) {
44- if (e.message.includes("called on non-object")) {
45- return `${namespace}.${name}`;
46- }
47- }
48- });
49- }).filter(Boolean);
50- * ```
27+ * Static methods on these globals are either not `this`-aware or supported being
28+ * called without `this`.
29+ *
30+ * - `Promise` is not in the list because it supports subclassing by using `this`
31+ * - `Array` is in the list because although it supports subclassing, the `this`
32+ * value defaults to `Array` when unbound
33+ *
34+ * This is now a language-design invariant: static methods are never `this`-aware
35+ * because TC39 wants to make `array.map(Class.method)` work!
5136 */
52- const nativelyNotBoundMembers = new Set ( [
53- 'Promise.all' ,
54- 'Promise.race' ,
55- 'Promise.resolve' ,
56- 'Promise.reject' ,
57- 'Promise.allSettled' ,
58- 'Object.defineProperties' ,
59- 'Object.defineProperty' ,
60- 'Reflect.defineProperty' ,
61- 'Reflect.deleteProperty' ,
62- 'Reflect.get' ,
63- 'Reflect.getOwnPropertyDescriptor' ,
64- 'Reflect.getPrototypeOf' ,
65- 'Reflect.has' ,
66- 'Reflect.isExtensible' ,
67- 'Reflect.ownKeys' ,
68- 'Reflect.preventExtensions' ,
69- 'Reflect.set' ,
70- 'Reflect.setPrototypeOf' ,
71- ] ) ;
7237const SUPPORTED_GLOBALS = [
7338 'Number' ,
7439 'Object' ,
@@ -78,31 +43,30 @@ const SUPPORTED_GLOBALS = [
7843 'Array' ,
7944 'Proxy' ,
8045 'Date' ,
81- 'Infinity' ,
8246 'Atomics' ,
8347 'Reflect' ,
8448 'console' ,
8549 'Math' ,
8650 'JSON' ,
8751 'Intl' ,
8852] as const ;
89- const nativelyBoundMembers = SUPPORTED_GLOBALS . map ( namespace => {
90- if ( ! ( namespace in global ) ) {
91- // node.js might not have namespaces like Intl depending on compilation options
92- // https://nodejs.org/api/intl.html#intl_options_for_building_node_js
93- return [ ] ;
94- }
95- const object = global [ namespace ] ;
96- return Object . getOwnPropertyNames ( object )
97- . filter (
98- name =>
99- ! name . startsWith ( '_' ) &&
100- typeof ( object as Record < string , unknown > ) [ name ] === 'function' ,
101- )
102- . map ( name => ` ${ namespace } . ${ name } ` ) ;
103- } )
104- . reduce ( ( arr , names ) => arr . concat ( names ) , [ ] )
105- . filter ( name => ! nativelyNotBoundMembers . has ( name ) ) ;
53+ const nativelyBoundMembers = new Set (
54+ SUPPORTED_GLOBALS . flatMap ( namespace => {
55+ if ( ! ( namespace in global ) ) {
56+ // node.js might not have namespaces like Intl depending on compilation options
57+ // https://nodejs.org/api/intl.html#intl_options_for_building_node_js
58+ return [ ] ;
59+ }
60+ const object = global [ namespace ] ;
61+ return Object . getOwnPropertyNames ( object )
62+ . filter (
63+ name =>
64+ ! name . startsWith ( '_' ) &&
65+ typeof ( object as Record < string , unknown > ) [ name ] === 'function' ,
66+ )
67+ . map ( name => ` ${ namespace } . ${ name } ` ) ;
68+ } ) ,
69+ ) ;
10670
10771const isNotImported = (
10872 symbol : ts . Symbol ,
@@ -201,7 +165,7 @@ export default createRule<Options, MessageIds>({
201165
202166 if (
203167 objectSymbol &&
204- nativelyBoundMembers . includes ( getMemberFullName ( node ) ) &&
168+ nativelyBoundMembers . has ( getMemberFullName ( node ) ) &&
205169 isNotImported ( objectSymbol , currentSourceFile )
206170 ) {
207171 return ;
@@ -232,7 +196,7 @@ export default createRule<Options, MessageIds>({
232196 if (
233197 notImported &&
234198 isIdentifier ( initNode ) &&
235- nativelyBoundMembers . includes (
199+ nativelyBoundMembers . has (
236200 `${ initNode . name } .${ property . key . name } ` ,
237201 )
238202 ) {
0 commit comments