@@ -2,46 +2,63 @@ import { AttachedScope, attachScopes } from '@rollup/pluginutils';
22import { Node , walk } from 'estree-walker' ;
33import isReference from 'is-reference' ;
44import type { AstNode } from 'rollup' ;
5+ import type { MemberExpression } from 'estree' ;
56
6- const gmAPIs = [
7- 'GM_info' ,
8- 'GM_getValue' ,
9- 'GM_getValues' ,
10- 'GM_setValue' ,
11- 'GM_setValues' ,
12- 'GM_deleteValue' ,
13- 'GM_deleteValues' ,
14- 'GM_listValues' ,
15- 'GM_addValueChangeListener' ,
16- 'GM_removeValueChangeListener' ,
17- 'GM_getResourceText' ,
18- 'GM_getResourceURL' ,
19- 'GM_addElement' ,
20- 'GM_addStyle' ,
21- 'GM_openInTab' ,
22- 'GM_registerMenuCommand' ,
23- 'GM_unregisterMenuCommand' ,
24- 'GM_notification' ,
25- 'GM_setClipboard' ,
26- 'GM_xmlhttpRequest' ,
27- 'GM_download' ,
28- ] ;
297const META_START = '// ==UserScript==' ;
308const META_END = '// ==/UserScript==' ;
9+ const GRANTS_REGEXP = / ^ u n s a f e W i n d o w | G M [ . _ ] [ a - z A - Z 0 - 9 _ ] + / ;
3110
32- export function collectGmApi ( ast : AstNode ) {
11+ export function collectGrants ( ast : AstNode ) {
3312 let scope = attachScopes ( ast , 'scope' ) ;
3413 const grantSetPerFile = new Set ( ) ;
3514 walk ( ast as Node , {
3615 enter ( node : Node & { scope : AttachedScope } , parent ) {
3716 if ( node . scope ) scope = node . scope ;
17+
18+ if (
19+ node . type === 'MemberExpression' &&
20+ isReference ( node , parent )
21+ ) {
22+ function getMemberExpressionFullNameRecursive ( astNode : MemberExpression ) : string | null {
23+ if ( astNode . property . type !== 'Identifier' ) {
24+ return null ;
25+ }
26+
27+ switch ( astNode . object . type ) {
28+ case 'MemberExpression' : {
29+ const nameSoFar = getMemberExpressionFullNameRecursive ( astNode . object ) ;
30+ if ( nameSoFar == null ) {
31+ return null ;
32+ }
33+
34+ return `${ nameSoFar } .${ astNode . property . name } `
35+ }
36+ case 'Identifier' : {
37+ return `${ astNode . object . name } .${ astNode . property . name } ` ;
38+ }
39+ default : {
40+ return null ;
41+ }
42+ }
43+ }
44+
45+ const fullName = getMemberExpressionFullNameRecursive ( node ) ;
46+ const match = GRANTS_REGEXP . exec ( fullName ) ;
47+ if ( match ) {
48+ grantSetPerFile . add ( match [ 0 ] ) ;
49+
50+ this . skip ( ) ;
51+ }
52+ }
53+
3854 if (
3955 node . type === 'Identifier' &&
4056 isReference ( node , parent ) &&
4157 ! scope . contains ( node . name )
4258 ) {
43- if ( gmAPIs . includes ( node . name ) ) {
44- grantSetPerFile . add ( node . name ) ;
59+ const match = GRANTS_REGEXP . exec ( node . name ) ;
60+ if ( match ) {
61+ grantSetPerFile . add ( match [ 0 ] ) ;
4562 }
4663 }
4764 } ,
0 commit comments