@@ -982,162 +982,185 @@ builtinScriptlets.push({
982
982
fn : setConstant ,
983
983
} ) ;
984
984
function setConstant (
985
- chain = '' ,
986
- cValue = ''
985
+ arg1 = '' ,
986
+ arg2 = '' ,
987
+ arg3 = 0
987
988
) {
989
+ const details = typeof arg1 !== 'object'
990
+ ? { prop : arg1 , value : arg2 , runAt : parseInt ( arg3 , 10 ) || 0 }
991
+ : arg1 ;
992
+ const { prop : chain = '' , value : cValue = '' } = details ;
988
993
if ( typeof chain !== 'string' ) { return ; }
989
994
if ( chain === '' ) { return ; }
990
- const trappedProp = ( ( ) => {
991
- const pos = chain . lastIndexOf ( '.' ) ;
992
- if ( pos === - 1 ) { return chain ; }
993
- return chain . slice ( pos + 1 ) ;
994
- } ) ( ) ;
995
- if ( trappedProp === '' ) { return ; }
996
- const thisScript = document . currentScript ;
997
- const objectDefineProperty = Object . defineProperty . bind ( Object ) ;
998
- const cloakFunc = fn => {
999
- objectDefineProperty ( fn , 'name' , { value : trappedProp } ) ;
1000
- const proxy = new Proxy ( fn , {
1001
- defineProperty ( target , prop ) {
1002
- if ( prop !== 'toString' ) {
1003
- return Reflect . deleteProperty ( ...arguments ) ;
1004
- }
1005
- return true ;
1006
- } ,
1007
- deleteProperty ( target , prop ) {
1008
- if ( prop !== 'toString' ) {
1009
- return Reflect . deleteProperty ( ...arguments ) ;
1010
- }
1011
- return true ;
1012
- } ,
1013
- get ( target , prop ) {
1014
- if ( prop === 'toString' ) {
1015
- return function ( ) {
1016
- return `function ${ trappedProp } () { [native code] }` ;
1017
- } . bind ( null ) ;
1018
- }
1019
- return Reflect . get ( ...arguments ) ;
1020
- } ,
1021
- } ) ;
1022
- return proxy ;
1023
- } ;
1024
- if ( cValue === 'undefined' ) {
1025
- cValue = undefined ;
1026
- } else if ( cValue === 'false' ) {
1027
- cValue = false ;
1028
- } else if ( cValue === 'true' ) {
1029
- cValue = true ;
1030
- } else if ( cValue === 'null' ) {
1031
- cValue = null ;
1032
- } else if ( cValue === "''" ) {
1033
- cValue = '' ;
1034
- } else if ( cValue === '[]' ) {
1035
- cValue = [ ] ;
1036
- } else if ( cValue === '{}' ) {
1037
- cValue = { } ;
1038
- } else if ( cValue === 'noopFunc' ) {
1039
- cValue = cloakFunc ( function ( ) { } ) ;
1040
- } else if ( cValue === 'trueFunc' ) {
1041
- cValue = cloakFunc ( function ( ) { return true ; } ) ;
1042
- } else if ( cValue === 'falseFunc' ) {
1043
- cValue = cloakFunc ( function ( ) { return false ; } ) ;
1044
- } else if ( / ^ \d + $ / . test ( cValue ) ) {
1045
- cValue = parseFloat ( cValue ) ;
1046
- if ( isNaN ( cValue ) ) { return ; }
1047
- if ( Math . abs ( cValue ) > 0x7FFF ) { return ; }
1048
- } else {
1049
- return ;
1050
- }
1051
- let aborted = false ;
1052
- const mustAbort = function ( v ) {
1053
- if ( aborted ) { return true ; }
1054
- aborted =
1055
- ( v !== undefined && v !== null ) &&
1056
- ( cValue !== undefined && cValue !== null ) &&
1057
- ( typeof v !== typeof cValue ) ;
1058
- return aborted ;
1059
- } ;
1060
- // https://github.com/uBlockOrigin/uBlock-issues/issues/156
1061
- // Support multiple trappers for the same property.
1062
- const trapProp = function ( owner , prop , configurable , handler ) {
1063
- if ( handler . init ( owner [ prop ] ) === false ) { return ; }
1064
- const odesc = Object . getOwnPropertyDescriptor ( owner , prop ) ;
1065
- let prevGetter , prevSetter ;
1066
- if ( odesc instanceof Object ) {
1067
- owner [ prop ] = cValue ;
1068
- if ( odesc . get instanceof Function ) {
1069
- prevGetter = odesc . get ;
1070
- }
1071
- if ( odesc . set instanceof Function ) {
1072
- prevSetter = odesc . set ;
1073
- }
1074
- }
1075
- try {
1076
- objectDefineProperty ( owner , prop , {
1077
- configurable,
1078
- get ( ) {
1079
- if ( prevGetter !== undefined ) {
1080
- prevGetter ( ) ;
995
+ function setConstant ( chain , cValue ) {
996
+ const trappedProp = ( ( ) => {
997
+ const pos = chain . lastIndexOf ( '.' ) ;
998
+ if ( pos === - 1 ) { return chain ; }
999
+ return chain . slice ( pos + 1 ) ;
1000
+ } ) ( ) ;
1001
+ if ( trappedProp === '' ) { return ; }
1002
+ const thisScript = document . currentScript ;
1003
+ const objectDefineProperty = Object . defineProperty . bind ( Object ) ;
1004
+ const cloakFunc = fn => {
1005
+ objectDefineProperty ( fn , 'name' , { value : trappedProp } ) ;
1006
+ const proxy = new Proxy ( fn , {
1007
+ defineProperty ( target , prop ) {
1008
+ if ( prop !== 'toString' ) {
1009
+ return Reflect . deleteProperty ( ...arguments ) ;
1081
1010
}
1082
- return handler . getter ( ) ; // cValue
1011
+ return true ;
1083
1012
} ,
1084
- set ( a ) {
1085
- if ( prevSetter !== undefined ) {
1086
- prevSetter ( a ) ;
1013
+ deleteProperty ( target , prop ) {
1014
+ if ( prop !== 'toString' ) {
1015
+ return Reflect . deleteProperty ( ... arguments ) ;
1087
1016
}
1088
- handler . setter ( a ) ;
1089
- }
1017
+ return true ;
1018
+ } ,
1019
+ get ( target , prop ) {
1020
+ if ( prop === 'toString' ) {
1021
+ return function ( ) {
1022
+ return `function ${ trappedProp } () { [native code] }` ;
1023
+ } . bind ( null ) ;
1024
+ }
1025
+ return Reflect . get ( ...arguments ) ;
1026
+ } ,
1090
1027
} ) ;
1091
- } catch ( ex ) {
1028
+ return proxy ;
1029
+ } ;
1030
+ if ( cValue === 'undefined' ) {
1031
+ cValue = undefined ;
1032
+ } else if ( cValue === 'false' ) {
1033
+ cValue = false ;
1034
+ } else if ( cValue === 'true' ) {
1035
+ cValue = true ;
1036
+ } else if ( cValue === 'null' ) {
1037
+ cValue = null ;
1038
+ } else if ( cValue === "''" ) {
1039
+ cValue = '' ;
1040
+ } else if ( cValue === '[]' ) {
1041
+ cValue = [ ] ;
1042
+ } else if ( cValue === '{}' ) {
1043
+ cValue = { } ;
1044
+ } else if ( cValue === 'noopFunc' ) {
1045
+ cValue = cloakFunc ( function ( ) { } ) ;
1046
+ } else if ( cValue === 'trueFunc' ) {
1047
+ cValue = cloakFunc ( function ( ) { return true ; } ) ;
1048
+ } else if ( cValue === 'falseFunc' ) {
1049
+ cValue = cloakFunc ( function ( ) { return false ; } ) ;
1050
+ } else if ( / ^ \d + $ / . test ( cValue ) ) {
1051
+ cValue = parseFloat ( cValue ) ;
1052
+ if ( isNaN ( cValue ) ) { return ; }
1053
+ if ( Math . abs ( cValue ) > 0x7FFF ) { return ; }
1054
+ } else {
1055
+ return ;
1092
1056
}
1093
- } ;
1094
- const trapChain = function ( owner , chain ) {
1095
- const pos = chain . indexOf ( '.' ) ;
1096
- if ( pos === - 1 ) {
1097
- trapProp ( owner , chain , false , {
1057
+ let aborted = false ;
1058
+ const mustAbort = function ( v ) {
1059
+ if ( aborted ) { return true ; }
1060
+ aborted =
1061
+ ( v !== undefined && v !== null ) &&
1062
+ ( cValue !== undefined && cValue !== null ) &&
1063
+ ( typeof v !== typeof cValue ) ;
1064
+ return aborted ;
1065
+ } ;
1066
+ // https://github.com/uBlockOrigin/uBlock-issues/issues/156
1067
+ // Support multiple trappers for the same property.
1068
+ const trapProp = function ( owner , prop , configurable , handler ) {
1069
+ if ( handler . init ( configurable ? owner [ prop ] : cValue ) === false ) { return ; }
1070
+ const odesc = Object . getOwnPropertyDescriptor ( owner , prop ) ;
1071
+ let prevGetter , prevSetter ;
1072
+ if ( odesc instanceof Object ) {
1073
+ owner [ prop ] = cValue ;
1074
+ if ( odesc . get instanceof Function ) {
1075
+ prevGetter = odesc . get ;
1076
+ }
1077
+ if ( odesc . set instanceof Function ) {
1078
+ prevSetter = odesc . set ;
1079
+ }
1080
+ }
1081
+ try {
1082
+ objectDefineProperty ( owner , prop , {
1083
+ configurable,
1084
+ get ( ) {
1085
+ if ( prevGetter !== undefined ) {
1086
+ prevGetter ( ) ;
1087
+ }
1088
+ return handler . getter ( ) ; // cValue
1089
+ } ,
1090
+ set ( a ) {
1091
+ if ( prevSetter !== undefined ) {
1092
+ prevSetter ( a ) ;
1093
+ }
1094
+ handler . setter ( a ) ;
1095
+ }
1096
+ } ) ;
1097
+ } catch ( ex ) {
1098
+ }
1099
+ } ;
1100
+ const trapChain = function ( owner , chain ) {
1101
+ const pos = chain . indexOf ( '.' ) ;
1102
+ if ( pos === - 1 ) {
1103
+ trapProp ( owner , chain , false , {
1104
+ v : undefined ,
1105
+ init : function ( v ) {
1106
+ if ( mustAbort ( v ) ) { return false ; }
1107
+ this . v = v ;
1108
+ return true ;
1109
+ } ,
1110
+ getter : function ( ) {
1111
+ return document . currentScript === thisScript
1112
+ ? this . v
1113
+ : cValue ;
1114
+ } ,
1115
+ setter : function ( a ) {
1116
+ if ( mustAbort ( a ) === false ) { return ; }
1117
+ cValue = a ;
1118
+ }
1119
+ } ) ;
1120
+ return ;
1121
+ }
1122
+ const prop = chain . slice ( 0 , pos ) ;
1123
+ const v = owner [ prop ] ;
1124
+ chain = chain . slice ( pos + 1 ) ;
1125
+ if ( v instanceof Object || typeof v === 'object' && v !== null ) {
1126
+ trapChain ( v , chain ) ;
1127
+ return ;
1128
+ }
1129
+ trapProp ( owner , prop , true , {
1098
1130
v : undefined ,
1099
1131
init : function ( v ) {
1100
- if ( mustAbort ( v ) ) { return false ; }
1101
1132
this . v = v ;
1102
1133
return true ;
1103
1134
} ,
1104
1135
getter : function ( ) {
1105
- return document . currentScript === thisScript
1106
- ? this . v
1107
- : cValue ;
1136
+ return this . v ;
1108
1137
} ,
1109
1138
setter : function ( a ) {
1110
- if ( mustAbort ( a ) === false ) { return ; }
1111
- cValue = a ;
1139
+ this . v = a ;
1140
+ if ( a instanceof Object ) {
1141
+ trapChain ( a , chain ) ;
1142
+ }
1112
1143
}
1113
1144
} ) ;
1114
- return ;
1115
- }
1116
- const prop = chain . slice ( 0 , pos ) ;
1117
- const v = owner [ prop ] ;
1118
- chain = chain . slice ( pos + 1 ) ;
1119
- if ( v instanceof Object || typeof v === 'object' && v !== null ) {
1120
- trapChain ( v , chain ) ;
1121
- return ;
1122
- }
1123
- trapProp ( owner , prop , true , {
1124
- v : undefined ,
1125
- init : function ( v ) {
1126
- this . v = v ;
1127
- return true ;
1128
- } ,
1129
- getter : function ( ) {
1130
- return this . v ;
1131
- } ,
1132
- setter : function ( a ) {
1133
- this . v = a ;
1134
- if ( a instanceof Object ) {
1135
- trapChain ( a , chain ) ;
1136
- }
1137
- }
1138
- } ) ;
1145
+ } ;
1146
+ trapChain ( window , chain ) ;
1147
+ }
1148
+ const runAt = details . runAt ;
1149
+ if ( runAt === 0 ) {
1150
+ setConstant ( chain , cValue ) ; return ;
1151
+ }
1152
+ const docReadyState = ( ) => {
1153
+ return ( { loading : 1 , interactive : 2 , complete : 3 , } ) [ document . readyState ] || 0 ;
1154
+ } ;
1155
+ if ( docReadyState ( ) >= runAt ) {
1156
+ setConstant ( chain , cValue ) ; return ;
1157
+ }
1158
+ const onReadyStateChange = ( ) => {
1159
+ if ( docReadyState ( ) < runAt ) { return ; }
1160
+ setConstant ( chain , cValue ) ;
1161
+ document . removeEventListener ( 'readystatechange' , onReadyStateChange ) ;
1139
1162
} ;
1140
- trapChain ( window , chain ) ;
1163
+ document . addEventListener ( 'readystatechange' , onReadyStateChange ) ;
1141
1164
}
1142
1165
1143
1166
/******************************************************************************/
0 commit comments