1 package jspacker 2 3 import ( 4 "fmt" 5 "sort" 6 "strconv" 7 8 "vimagination.zapto.org/javascript" 9 "vimagination.zapto.org/parser" 10 ) 11 12 func jToken(data string) *javascript.Token { 13 return &javascript.Token{Token: parser.Token{Data: data}} 14 } 15 16 func (c *config) makeLoader() error { 17 promise := &javascript.MemberExpression{ 18 PrimaryExpression: &javascript.PrimaryExpression{ 19 IdentifierReference: jToken("Promise"), 20 }, 21 } 22 promiseResolve := &javascript.MemberExpression{ 23 MemberExpression: promise, 24 IdentifierName: jToken("resolve"), 25 } 26 trueAE := &javascript.AssignmentExpression{ 27 ConditionalExpression: javascript.WrapConditional(&javascript.PrimaryExpression{ 28 Literal: jToken("true"), 29 }), 30 } 31 object := &javascript.MemberExpression{ 32 PrimaryExpression: &javascript.PrimaryExpression{ 33 IdentifierReference: jToken("Object"), 34 }, 35 } 36 url := jToken("url") 37 wrappedURL := javascript.WrapConditional(&javascript.PrimaryExpression{ 38 IdentifierReference: url, 39 }) 40 importURL := javascript.WrapConditional(&javascript.CallExpression{ 41 ImportCall: &javascript.AssignmentExpression{ 42 ConditionalExpression: wrappedURL, 43 }, 44 }) 45 var include *javascript.AssignmentExpression 46 if !c.bare || c.parseDynamic { 47 exportArr := &javascript.ArrayLiteral{ 48 ElementList: make([]javascript.ArrayElement, 0, len(c.filesDone)), 49 } 50 urls := make([]string, 0, len(c.filesDone)) 51 imports := jToken("imports") 52 importsGet := &javascript.MemberExpression{ 53 MemberExpression: &javascript.MemberExpression{ 54 PrimaryExpression: &javascript.PrimaryExpression{ 55 IdentifierReference: imports, 56 }, 57 }, 58 IdentifierName: jToken("get"), 59 } 60 for url := range c.filesDone { 61 urls = append(urls, url) 62 } 63 sort.Strings(urls) 64 for _, url := range urls { 65 d := c.filesDone[url] 66 if c.bare && !d.dynamicRequirement { 67 continue 68 } 69 el := append(make([]javascript.ArrayElement, 0, len(d.exports)+1), javascript.ArrayElement{ 70 AssignmentExpression: javascript.AssignmentExpression{ 71 ConditionalExpression: javascript.WrapConditional(&javascript.PrimaryExpression{ 72 Literal: jToken(strconv.Quote(url)), 73 }), 74 }, 75 }) 76 props := make([]string, 0, len(d.exports)) 77 for prop := range d.exports { 78 props = append(props, prop) 79 } 80 sort.Strings(props) 81 for _, prop := range props { 82 binding := d.exports[prop] 83 propName := javascript.ArrayElement{ 84 AssignmentExpression: javascript.AssignmentExpression{ 85 ConditionalExpression: javascript.WrapConditional(&javascript.PrimaryExpression{ 86 Literal: jToken(strconv.Quote(prop)), 87 }), 88 }, 89 } 90 var ael []javascript.ArrayElement 91 if binding.binding == "" { 92 ael = []javascript.ArrayElement{ 93 propName, 94 { 95 AssignmentExpression: javascript.AssignmentExpression{ 96 ArrowFunction: &javascript.ArrowFunction{ 97 FormalParameters: &javascript.FormalParameters{}, 98 AssignmentExpression: &javascript.AssignmentExpression{ 99 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 100 MemberExpression: importsGet, 101 Arguments: &javascript.Arguments{ 102 ArgumentList: []javascript.Argument{ 103 { 104 AssignmentExpression: javascript.AssignmentExpression{ 105 ConditionalExpression: javascript.WrapConditional(&javascript.PrimaryExpression{ 106 Literal: jToken(strconv.Quote(binding.dependency.url)), 107 }), 108 }, 109 }, 110 }, 111 }, 112 }), 113 }, 114 }, 115 }, 116 }, 117 } 118 } else { 119 b := d.resolveExport(prop) 120 if b == nil { 121 return fmt.Errorf("error resolving export %s (%s): %w", prop, d.url, ErrInvalidExport) 122 } 123 ael = []javascript.ArrayElement{ 124 propName, 125 { 126 AssignmentExpression: javascript.AssignmentExpression{ 127 ArrowFunction: &javascript.ArrowFunction{ 128 FormalParameters: &javascript.FormalParameters{}, 129 AssignmentExpression: &javascript.AssignmentExpression{ 130 ConditionalExpression: javascript.WrapConditional(&javascript.PrimaryExpression{ 131 IdentifierReference: b.Token, 132 }), 133 }, 134 }, 135 }, 136 }, 137 } 138 } 139 el = append(el, javascript.ArrayElement{ 140 AssignmentExpression: javascript.AssignmentExpression{ 141 ConditionalExpression: javascript.WrapConditional(&javascript.ArrayLiteral{ 142 ElementList: ael, 143 }), 144 }, 145 }) 146 } 147 exportArr.ElementList = append(exportArr.ElementList, javascript.ArrayElement{ 148 AssignmentExpression: javascript.AssignmentExpression{ 149 ConditionalExpression: javascript.WrapConditional(&javascript.ArrayLiteral{ 150 ElementList: el, 151 }), 152 }, 153 }) 154 } 155 if len(exportArr.ElementList) > 0 { 156 mapt := jToken("map") 157 prop := jToken("prop") 158 get := jToken("get") 159 props := jToken("props") 160 include = &javascript.AssignmentExpression{ 161 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 162 MemberExpression: &javascript.MemberExpression{ 163 PrimaryExpression: &javascript.PrimaryExpression{ 164 ParenthesizedExpression: &javascript.ParenthesizedExpression{ 165 Expressions: []javascript.AssignmentExpression{ 166 { 167 ArrowFunction: &javascript.ArrowFunction{ 168 FormalParameters: &javascript.FormalParameters{}, 169 FunctionBody: &javascript.Block{ 170 StatementList: []javascript.StatementListItem{ 171 { 172 Declaration: &javascript.Declaration{ 173 LexicalDeclaration: &javascript.LexicalDeclaration{ 174 LetOrConst: javascript.Const, 175 BindingList: []javascript.LexicalBinding{ 176 { 177 BindingIdentifier: imports, 178 Initializer: &javascript.AssignmentExpression{ 179 ConditionalExpression: javascript.WrapConditional(javascript.MemberExpression{ 180 MemberExpression: &javascript.MemberExpression{ 181 PrimaryExpression: &javascript.PrimaryExpression{ 182 IdentifierReference: jToken("Map"), 183 }, 184 }, 185 Arguments: &javascript.Arguments{ 186 ArgumentList: []javascript.Argument{ 187 { 188 AssignmentExpression: javascript.AssignmentExpression{ 189 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 190 MemberExpression: &javascript.MemberExpression{ 191 MemberExpression: &javascript.MemberExpression{ 192 PrimaryExpression: &javascript.PrimaryExpression{ 193 ArrayLiteral: exportArr, 194 }, 195 }, 196 IdentifierName: mapt, 197 }, 198 Arguments: &javascript.Arguments{ 199 ArgumentList: []javascript.Argument{ 200 { 201 AssignmentExpression: javascript.AssignmentExpression{ 202 ArrowFunction: &javascript.ArrowFunction{ 203 FormalParameters: &javascript.FormalParameters{ 204 FormalParameterList: []javascript.BindingElement{ 205 { 206 ArrayBindingPattern: &javascript.ArrayBindingPattern{ 207 BindingElementList: []javascript.BindingElement{ 208 { 209 SingleNameBinding: url, 210 }, 211 }, 212 BindingRestElement: &javascript.BindingElement{ 213 SingleNameBinding: props, 214 }, 215 }, 216 }, 217 }, 218 }, 219 AssignmentExpression: &javascript.AssignmentExpression{ 220 ConditionalExpression: javascript.WrapConditional(&javascript.ArrayLiteral{ 221 ElementList: []javascript.ArrayElement{ 222 { 223 AssignmentExpression: javascript.AssignmentExpression{ 224 ConditionalExpression: wrappedURL, 225 }, 226 }, 227 { 228 AssignmentExpression: javascript.AssignmentExpression{ 229 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 230 MemberExpression: &javascript.MemberExpression{ 231 MemberExpression: object, 232 IdentifierName: jToken("freeze"), 233 }, 234 Arguments: &javascript.Arguments{ 235 ArgumentList: []javascript.Argument{ 236 { 237 AssignmentExpression: javascript.AssignmentExpression{ 238 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 239 MemberExpression: &javascript.MemberExpression{ 240 MemberExpression: object, 241 IdentifierName: jToken("defineProperties"), 242 }, 243 Arguments: &javascript.Arguments{ 244 ArgumentList: []javascript.Argument{ 245 { 246 AssignmentExpression: javascript.AssignmentExpression{ 247 ConditionalExpression: javascript.WrapConditional(&javascript.ObjectLiteral{}), 248 }, 249 }, 250 { 251 AssignmentExpression: javascript.AssignmentExpression{ 252 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 253 MemberExpression: &javascript.MemberExpression{ 254 MemberExpression: object, 255 IdentifierName: jToken("fromEntries"), 256 }, 257 Arguments: &javascript.Arguments{ 258 ArgumentList: []javascript.Argument{ 259 { 260 AssignmentExpression: javascript.AssignmentExpression{ 261 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 262 MemberExpression: &javascript.MemberExpression{ 263 MemberExpression: &javascript.MemberExpression{ 264 PrimaryExpression: &javascript.PrimaryExpression{ 265 IdentifierReference: props, 266 }, 267 }, 268 IdentifierName: mapt, 269 }, 270 Arguments: &javascript.Arguments{ 271 ArgumentList: []javascript.Argument{ 272 { 273 AssignmentExpression: javascript.AssignmentExpression{ 274 ArrowFunction: &javascript.ArrowFunction{ 275 FormalParameters: &javascript.FormalParameters{ 276 FormalParameterList: []javascript.BindingElement{ 277 { 278 ArrayBindingPattern: &javascript.ArrayBindingPattern{ 279 BindingElementList: []javascript.BindingElement{ 280 { 281 SingleNameBinding: prop, 282 }, 283 { 284 SingleNameBinding: get, 285 }, 286 }, 287 }, 288 }, 289 }, 290 }, 291 AssignmentExpression: &javascript.AssignmentExpression{ 292 ConditionalExpression: javascript.WrapConditional(&javascript.ArrayLiteral{ 293 ElementList: []javascript.ArrayElement{ 294 { 295 AssignmentExpression: javascript.AssignmentExpression{ 296 ConditionalExpression: javascript.WrapConditional(&javascript.PrimaryExpression{ 297 IdentifierReference: prop, 298 }), 299 }, 300 }, 301 { 302 AssignmentExpression: javascript.AssignmentExpression{ 303 ConditionalExpression: javascript.WrapConditional(&javascript.ObjectLiteral{ 304 PropertyDefinitionList: []javascript.PropertyDefinition{ 305 { 306 PropertyName: &javascript.PropertyName{ 307 LiteralPropertyName: jToken("enumerable"), 308 }, 309 AssignmentExpression: trueAE, 310 }, 311 { 312 PropertyName: &javascript.PropertyName{ 313 LiteralPropertyName: get, 314 }, 315 AssignmentExpression: &javascript.AssignmentExpression{ 316 ConditionalExpression: javascript.WrapConditional(&javascript.PrimaryExpression{ 317 IdentifierReference: get, 318 }), 319 }, 320 }, 321 }, 322 }), 323 }, 324 }, 325 }, 326 }), 327 }, 328 }, 329 }, 330 }, 331 }, 332 }, 333 }), 334 }, 335 }, 336 }, 337 }, 338 }), 339 }, 340 }, 341 }, 342 }, 343 }), 344 }, 345 }, 346 }, 347 }, 348 }), 349 }, 350 }, 351 }, 352 }), 353 }, 354 }, 355 }, 356 }, 357 }, 358 }, 359 }), 360 }, 361 }, 362 }, 363 }, 364 }), 365 }, 366 }, 367 }, 368 }, 369 }, 370 }, 371 { 372 Statement: &javascript.Statement{ 373 Type: javascript.StatementReturn, 374 ExpressionStatement: &javascript.Expression{ 375 Expressions: []javascript.AssignmentExpression{ 376 { 377 ArrowFunction: &javascript.ArrowFunction{ 378 BindingIdentifier: url, 379 AssignmentExpression: &javascript.AssignmentExpression{ 380 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 381 MemberExpression: promiseResolve, 382 Arguments: &javascript.Arguments{ 383 ArgumentList: []javascript.Argument{ 384 { 385 AssignmentExpression: javascript.AssignmentExpression{ 386 ConditionalExpression: &javascript.ConditionalExpression{ 387 CoalesceExpression: &javascript.CoalesceExpression{ 388 CoalesceExpressionHead: &javascript.CoalesceExpression{ 389 BitwiseORExpression: javascript.WrapConditional(&javascript.CallExpression{ 390 MemberExpression: importsGet, 391 Arguments: &javascript.Arguments{ 392 ArgumentList: []javascript.Argument{ 393 { 394 AssignmentExpression: javascript.AssignmentExpression{ 395 ConditionalExpression: wrappedURL, 396 }, 397 }, 398 }, 399 }, 400 }).LogicalORExpression.LogicalANDExpression.BitwiseORExpression, 401 }, 402 BitwiseORExpression: importURL.LogicalORExpression.LogicalANDExpression.BitwiseORExpression, 403 }, 404 }, 405 }, 406 }, 407 }, 408 }, 409 }), 410 }, 411 }, 412 }, 413 }, 414 }, 415 }, 416 }, 417 }, 418 }, 419 }, 420 }, 421 }, 422 }, 423 }, 424 }, 425 Arguments: &javascript.Arguments{}, 426 }), 427 } 428 } 429 } 430 if include == nil { 431 return nil 432 } 433 globalThis := &javascript.PrimaryExpression{ 434 IdentifierReference: jToken("globalThis"), 435 } 436 value := &javascript.PropertyName{ 437 LiteralPropertyName: jToken("value"), 438 } 439 c.statementList[0] = javascript.StatementListItem{ 440 Statement: &javascript.Statement{ 441 ExpressionStatement: &javascript.Expression{ 442 Expressions: []javascript.AssignmentExpression{ 443 { 444 ConditionalExpression: javascript.WrapConditional(&javascript.CallExpression{ 445 MemberExpression: &javascript.MemberExpression{ 446 MemberExpression: object, 447 IdentifierName: jToken("defineProperty"), 448 }, 449 Arguments: &javascript.Arguments{ 450 ArgumentList: []javascript.Argument{ 451 { 452 AssignmentExpression: javascript.AssignmentExpression{ 453 ConditionalExpression: javascript.WrapConditional(globalThis), 454 }, 455 }, 456 { 457 AssignmentExpression: javascript.AssignmentExpression{ 458 ConditionalExpression: javascript.WrapConditional(&javascript.PrimaryExpression{ 459 Literal: &javascript.Token{ 460 Token: parser.Token{ 461 Data: "\"include\"", 462 }, 463 }, 464 }), 465 }, 466 }, 467 { 468 AssignmentExpression: javascript.AssignmentExpression{ 469 ConditionalExpression: javascript.WrapConditional(&javascript.ObjectLiteral{ 470 PropertyDefinitionList: []javascript.PropertyDefinition{ 471 { 472 PropertyName: value, 473 AssignmentExpression: include, 474 }, 475 }, 476 }), 477 }, 478 }, 479 }, 480 }, 481 }), 482 }, 483 }, 484 }, 485 }, 486 } 487 return nil 488 } 489