@@ -6,27 +6,28 @@ enum RewriteType {
6
6
Replace = 1 ,
7
7
}
8
8
9
- type Rewrite =
9
+ type Rewrite = {
10
+ start : number ;
11
+ } & (
10
12
| {
11
13
type : RewriteType . Insert ;
12
- // offset before this rewrite
13
- offset : number ;
14
- // start of insertion
15
- start : number ;
16
- // size of insertion
17
14
size : number ;
18
15
}
19
16
| {
20
17
type : RewriteType . Replace ;
21
- // offset before this rewrite
22
- offset : number ;
23
- // start of replacement
24
- start : number ;
25
- // end of replacement
26
18
end : number ;
27
- // old string
28
19
str : string ;
29
- } ;
20
+ }
21
+ ) ;
22
+
23
+ function getEnd ( rewrite : Rewrite ) : number {
24
+ if ( rewrite . type === RewriteType . Insert ) {
25
+ return rewrite . start + rewrite . size ;
26
+ } else if ( rewrite . type === RewriteType . Replace ) {
27
+ return rewrite . end ;
28
+ }
29
+ throw "unreachable" ;
30
+ }
30
31
31
32
const sourcemaps : Record < string , Rewrite [ ] > = { } ;
32
33
@@ -35,49 +36,53 @@ export const enabled = (client: ScramjetClient) =>
35
36
36
37
export default function ( client : ScramjetClient , self : Self ) {
37
38
// every script will push a sourcemap
38
- Object . defineProperty ( self , $scramjet . config . globals . pushsourcemapfn , {
39
- value : ( buf : Array < number > , tag : string ) => {
40
- const sourcemap = Uint8Array . from ( buf ) ;
41
- const view = new DataView ( sourcemap . buffer ) ;
42
- const decoder = new TextDecoder ( "utf-8" ) ;
43
-
44
- const rewrites = [ ] ;
45
-
46
- const rewritelen = view . getUint32 ( 0 , true ) ;
47
- let cursor = 0 ;
48
- for ( let i = 0 ; i < rewritelen ; i ++ ) {
49
- const type = view . getUint8 ( cursor ) as RewriteType ;
50
- cursor += 1 ;
51
-
52
- if ( type == RewriteType . Insert ) {
53
- const offset = view . getUint32 ( cursor , true ) ;
54
- cursor += 4 ;
55
- const start = view . getUint32 ( cursor , true ) ;
56
- cursor += 4 ;
57
- const size = view . getUint32 ( cursor , true ) ;
58
- cursor += 4 ;
59
-
60
- rewrites . push ( { type, offset, start, size } ) ;
61
- } else if ( type == RewriteType . Replace ) {
62
- const offset = view . getUint32 ( cursor , true ) ;
63
- cursor += 4 ;
64
- const start = view . getUint32 ( cursor , true ) ;
65
- cursor += 4 ;
66
- const end = view . getUint32 ( cursor , true ) ;
67
- cursor += 4 ;
68
-
69
- const str = decoder . decode ( sourcemap . subarray ( start , end ) ) ;
70
-
71
- rewrites . push ( { type, offset, start, end, str } ) ;
39
+ Object . defineProperty (
40
+ self ,
41
+ globalThis . $scramjet . config . globals . pushsourcemapfn ,
42
+ {
43
+ value : ( buf : Array < number > , tag : string ) => {
44
+ const sourcemap = Uint8Array . from ( buf ) ;
45
+ const view = new DataView ( sourcemap . buffer ) ;
46
+ const decoder = new TextDecoder ( "utf-8" ) ;
47
+
48
+ const rewrites : Rewrite [ ] = [ ] ;
49
+
50
+ const rewritelen = view . getUint32 ( 0 , true ) ;
51
+ let cursor = 4 ;
52
+ for ( let i = 0 ; i < rewritelen ; i ++ ) {
53
+ const type = view . getUint8 ( cursor ) as RewriteType ;
54
+ cursor += 1 ;
55
+
56
+ if ( type == RewriteType . Insert ) {
57
+ const start = view . getUint32 ( cursor , true ) ;
58
+ cursor += 4 ;
59
+ const size = view . getUint32 ( cursor , true ) ;
60
+ cursor += 4 ;
61
+
62
+ rewrites . push ( { type, start, size } ) ;
63
+ } else if ( type == RewriteType . Replace ) {
64
+ const start = view . getUint32 ( cursor , true ) ;
65
+ cursor += 4 ;
66
+ const end = view . getUint32 ( cursor , true ) ;
67
+ cursor += 4 ;
68
+ const len = view . getUint32 ( cursor , true ) ;
69
+ cursor += 4 ;
70
+
71
+ const str = decoder . decode (
72
+ sourcemap . subarray ( cursor , cursor + len )
73
+ ) ;
74
+
75
+ rewrites . push ( { type, start, end, str } ) ;
76
+ }
72
77
}
73
- }
74
78
75
- sourcemaps [ tag ] = rewrites ;
76
- } ,
77
- enumerable : false ,
78
- writable : false ,
79
- configurable : false ,
80
- } ) ;
79
+ sourcemaps [ tag ] = rewrites ;
80
+ } ,
81
+ enumerable : false ,
82
+ writable : false ,
83
+ configurable : false ,
84
+ }
85
+ ) ;
81
86
82
87
const scramtag_ident = "/*scramtag " ;
83
88
@@ -86,7 +91,6 @@ export default function (client: ScramjetClient, self: Self) {
86
91
client . Proxy ( "Function.prototype.toString" , {
87
92
apply ( ctx ) {
88
93
let stringified : string = ctx . fn . call ( ctx . this ) ;
89
- let newString = "" ;
90
94
91
95
// every function rewritten will have a scramtag comment
92
96
// it will look like this:
@@ -106,39 +110,50 @@ export default function (client: ScramjetClient, self: Self) {
106
110
107
111
// subtracting that from the index of the scramtag gives us the starting index of the function relative to the entire file
108
112
const absindex = abstagindex - scramtagstart ;
113
+ const endindex = absindex + stringified . length ;
109
114
110
115
const scramtagend = stringified . indexOf ( "*/" , scramtagstart ) ;
111
116
const tag = stringified . substring ( firstspace + 1 , scramtagend ) ;
112
117
113
- // delete all scramtags inside the function (and nested ones!!)
114
- stringified = stringified . replace ( / \/ \* s c r a m t a g .* ?\* \/ / g, "" ) ;
118
+ const rewrites = sourcemaps [ tag ] ;
115
119
116
- const maps = sourcemaps [ tag ] ;
120
+ if ( ! rewrites ) {
121
+ console . warn ( "failed to get rewrites for tag" , tag ) ;
122
+ return ctx . return ( stringified ) ;
123
+ }
117
124
118
125
let i = 0 ;
119
- let offset = 0 ;
120
-
121
- let j = 0 ;
122
- while ( j < maps . length ) {
123
- /* TODO
124
- const [str, start, end] = maps[j];
125
- if (start < absindex) {
126
- j++;
127
- continue ;
128
- }
129
- if (start - absindex + offset > stringified.length) break;
126
+ // skip all rewrites in the file before the fn
127
+ while ( i < rewrites . length ) {
128
+ if ( rewrites [ i ] . start < absindex ) i ++ ;
129
+ else break ;
130
+ }
131
+
132
+ let end = i ;
133
+ while ( end < rewrites . length ) {
134
+ if ( getEnd ( rewrites [ end ] ) < endindex ) end ++ ;
135
+ else break ;
136
+ }
130
137
131
- // ooh i should really document this before i forget how it works
132
- newString += stringified.slice(i, start - absindex + offset);
133
- newString += str;
134
- offset += end - start - str.length;
135
- i = start - absindex + offset + str.length;
138
+ const fnrewrites = rewrites . slice ( i , end ) ;
136
139
137
- j++;
138
- */
140
+ let newString = "" ;
141
+ let lastpos = absindex ;
142
+
143
+ for ( const rewrite of fnrewrites ) {
144
+ newString += stringified . slice ( lastpos , rewrite . start ) ;
145
+
146
+ if ( rewrite . type === RewriteType . Insert ) {
147
+ lastpos = rewrite . start + rewrite . size ;
148
+ } else if ( rewrite . type === RewriteType . Replace ) {
149
+ newString += rewrite . str ;
150
+ lastpos = rewrite . end ;
151
+ } else {
152
+ throw "unreachable" ;
153
+ }
139
154
}
140
155
141
- newString += stringified . slice ( i ) ;
156
+ newString += stringified . slice ( lastpos ) ;
142
157
143
158
return ctx . return ( newString ) ;
144
159
} ,
0 commit comments