Fossil
Check-in [38f3d978]
Not logged in

Many hyperlinks are disabled.
Use anonymous login to enable hyperlinks.

Overview
Comment:Reduce the number of jsmode options to three: inline, separate, bundled.
Downloads: Tarball | ZIP archive | SQL archive
Timelines: family | ancestors | descendants | both | refactor-js-handling
Files: files | file ages | folders
SHA3-256: 38f3d9785b372d5a518b6e1ea04a0b481115ab31fbd60c26091d7286f2706388
User & Date: drh 2020-07-31 21:32:58
Context
2020-07-31
21:47
Replace various style_emit_script...() calls with builtin_request_js(). (check-in: 699a977c user: drh tags: refactor-js-handling)
21:32
Reduce the number of jsmode options to three: inline, separate, bundled. (check-in: 38f3d978 user: drh tags: refactor-js-handling)
20:16
Fix lines for separate JS modes. (check-in: 314bb157 user: drh tags: refactor-js-handling)
Changes
Hide Diffs Unified Diffs Ignore Whitespace Patch

Changes to src/builtin.c.

222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
...
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
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
  int nSent;           /* Number of slots in aReq[] fulfilled */
  int eDelivery;       /* Delivery mechanism */
} builtin;

#if INTERFACE
/* Various delivery mechanisms.  The 0 option is the default.
*/
#define JS_INLINE_BATCH  0    /* inline, batched together */
#define JS_INLINE_IMM    1    /* inline, as soon as requested */
#define JS_SEP_BATCH     2    /* Separate resources, batched */
#define JS_SEP_IMM       3    /* Separate resources, as requested */
#define JS_BUNDLED       4    /* Single separate resource */
#endif /* INTERFACE */

/*
** The argument is a request to change the javascript delivery mode.
** The argument is a string which is a command-line option or CGI
** parameter.  Try to match it against one of the delivery options
** and set things up accordingly.  Throw an error if no match unless
** bSilent is true.
*/
void builtin_set_js_delivery_mode(const char *zMode, int bSilent){
  if( zMode==0 ) return;
  if( strcmp(zMode, "inline")==0 ){
    builtin.eDelivery = JS_INLINE_BATCH;
  }else
  if( strcmp(zMode, "inline-imm")==0 ){
    builtin.eDelivery = JS_INLINE_IMM;
  }else
  if( strcmp(zMode, "sep")==0 ){
    builtin.eDelivery = JS_SEP_BATCH;
  }else
  if( strcmp(zMode, "sep-imm")==0 ){
    builtin.eDelivery = JS_SEP_IMM;
  }else
  if( strcmp(zMode, "bundled")==0 ){
    builtin.eDelivery = JS_BUNDLED;
  }else if( !bSilent ){
    fossil_fatal("unknown javascript delivery mode \"%s\" - should be"
                 " one of: inline inline-immediate separate"
                 " separate-immediate bundled", zMode);
  }
}

/*
** The caller wants the Javascript file named by zFilename to be
** included in the generated page.  Add the file to the queue of
** requested javascript resources, if it is not there already.
................................................................................
  for(j=0; j<builtin.nReq; j++){
    if( builtin.aReq[j]==i ) return;  /* Already queued or sent */
  }
  if( builtin.nReq>=count(builtin.aReq) ){
    fossil_panic("too many javascript files requested");
  }
  builtin.aReq[builtin.nReq++] = i;
  if( builtin.eDelivery==JS_INLINE_IMM
   || builtin.eDelivery==JS_SEP_IMM
  ){
    builtin_fulfill_js_requests();
  }
}

/*
** Fulfill all pending requests for javascript files.
**
** The current implementation delivers all javascript in-line.  However,
** the caller should not depend on this.  Future changes to this routine
** might choose to deliver javascript as separate resources.
*/
void builtin_fulfill_js_requests(void){
  if( builtin.nSent>=builtin.nReq ) return;  /* nothing to do */
  switch( builtin.eDelivery ){
    case JS_INLINE_BATCH:
    case JS_INLINE_IMM: {
      CX("<script nonce='%h'>\n",style_nonce());
      do{
        int i = builtin.aReq[builtin.nSent++];
        CX("/* %s */\n", aBuiltinFiles[i].zName);
        cgi_append_content((const char*)aBuiltinFiles[i].pData,
                           aBuiltinFiles[i].nByte);
      }while( builtin.nSent<builtin.nReq );
      CX("</script>\n");
      break;
    }
    case JS_SEP_BATCH:















    case JS_SEP_IMM: {
      /* Each JS file as a separate resource */
      while( builtin.nSent<builtin.nReq ){
        int i = builtin.aReq[builtin.nSent++];
        CX("<script src='%R/builtin?name=%t&id=%.8s'></script>\n",
              aBuiltinFiles[i].zName, fossil_exe_id());
      }
      break;
    }
    case JS_BUNDLED: {
      Blob aList;
      blob_init(&aList,0,0);
      while( builtin.nSent<builtin.nReq ){
        blob_appendf(&aList, ",%d", builtin.aReq[builtin.nSent++]+1);
      }
      CX("<script src='%R/builtin?m=%s&id=%.8s'></script>\n",
         blob_str(&aList)+1, fossil_exe_id());
      blob_reset(&aList);
    }
  }
}







|
|
|
|
<












<
<
<
|

|
<
<
<
|





<
|







 







<
<
<
<
<












|
<










|
>
>
>
>
>
>
>
>
>
>
>
>
>
>
>
|








<
<
<
<
<
|
<
<
<
|
<
<
222
223
224
225
226
227
228
229
230
231
232

233
234
235
236
237
238
239
240
241
242
243
244



245
246
247



248
249
250
251
252
253

254
255
256
257
258
259
260
261
...
284
285
286
287
288
289
290





291
292
293
294
295
296
297
298
299
300
301
302
303

304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338





339



340


  int nSent;           /* Number of slots in aReq[] fulfilled */
  int eDelivery;       /* Delivery mechanism */
} builtin;

#if INTERFACE
/* Various delivery mechanisms.  The 0 option is the default.
*/
#define JS_INLINE   0    /* inline, batched together at end of file */
#define JS_SEPARATE 1    /* Separate HTTP request for each JS file */
#define JS_BUNDLED  2    /* One HTTP request to load all JS files */
                         /* concatenated together into a bundle */

#endif /* INTERFACE */

/*
** The argument is a request to change the javascript delivery mode.
** The argument is a string which is a command-line option or CGI
** parameter.  Try to match it against one of the delivery options
** and set things up accordingly.  Throw an error if no match unless
** bSilent is true.
*/
void builtin_set_js_delivery_mode(const char *zMode, int bSilent){
  if( zMode==0 ) return;
  if( strcmp(zMode, "inline")==0 ){



    builtin.eDelivery = JS_INLINE;
  }else
  if( strcmp(zMode, "separate")==0 ){



    builtin.eDelivery = JS_SEPARATE;
  }else
  if( strcmp(zMode, "bundled")==0 ){
    builtin.eDelivery = JS_BUNDLED;
  }else if( !bSilent ){
    fossil_fatal("unknown javascript delivery mode \"%s\" - should be"

                 " one of: inline separate bundled", zMode);
  }
}

/*
** The caller wants the Javascript file named by zFilename to be
** included in the generated page.  Add the file to the queue of
** requested javascript resources, if it is not there already.
................................................................................
  for(j=0; j<builtin.nReq; j++){
    if( builtin.aReq[j]==i ) return;  /* Already queued or sent */
  }
  if( builtin.nReq>=count(builtin.aReq) ){
    fossil_panic("too many javascript files requested");
  }
  builtin.aReq[builtin.nReq++] = i;





}

/*
** Fulfill all pending requests for javascript files.
**
** The current implementation delivers all javascript in-line.  However,
** the caller should not depend on this.  Future changes to this routine
** might choose to deliver javascript as separate resources.
*/
void builtin_fulfill_js_requests(void){
  if( builtin.nSent>=builtin.nReq ) return;  /* nothing to do */
  switch( builtin.eDelivery ){
    case JS_INLINE: {

      CX("<script nonce='%h'>\n",style_nonce());
      do{
        int i = builtin.aReq[builtin.nSent++];
        CX("/* %s */\n", aBuiltinFiles[i].zName);
        cgi_append_content((const char*)aBuiltinFiles[i].pData,
                           aBuiltinFiles[i].nByte);
      }while( builtin.nSent<builtin.nReq );
      CX("</script>\n");
      break;
    }
    case JS_BUNDLED: {
      if( builtin.nSent+1<builtin.nReq ){
        Blob aList;
        blob_init(&aList,0,0);
        while( builtin.nSent<builtin.nReq ){
          blob_appendf(&aList, ",%d", builtin.aReq[builtin.nSent++]+1);
        }
        CX("<script src='%R/builtin?m=%s&id=%.8s'></script>\n",
           blob_str(&aList)+1, fossil_exe_id());
        blob_reset(&aList);
        break;
      }
      /* If there is only one JS file, fall through into the
      ** JS_SEPARATE case below. */
      /*FALLTHROUGH*/
    }
    case JS_SEPARATE: {
      /* Each JS file as a separate resource */
      while( builtin.nSent<builtin.nReq ){
        int i = builtin.aReq[builtin.nSent++];
        CX("<script src='%R/builtin?name=%t&id=%.8s'></script>\n",
              aBuiltinFiles[i].zName, fossil_exe_id());
      }
      break;
    }





  }



}


Changes to src/codecheck1.c.

405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
  { "mprintf",                 1, FMT_SAFE },
  { "pop3_print",              2, FMT_SAFE },
  { "smtp_send_line",          2, FMT_SAFE },
  { "smtp_server_send",        2, FMT_SAFE },
  { "socket_set_errmsg",       1, FMT_SAFE },
  { "ssl_set_errmsg",          1, FMT_SAFE },
  { "style_header",            1, FMT_HTML },
  { "style_js_onload",         1, FMT_HTML },
  { "style_set_current_page",  1, FMT_URL },
  { "style_submenu_element",   2, FMT_URL },
  { "style_submenu_sql",       3, FMT_SQL },
  { "webpage_error",           1, FMT_SAFE },
  { "xhref",                   2, FMT_URL },
};








<







405
406
407
408
409
410
411

412
413
414
415
416
417
418
  { "mprintf",                 1, FMT_SAFE },
  { "pop3_print",              2, FMT_SAFE },
  { "smtp_send_line",          2, FMT_SAFE },
  { "smtp_server_send",        2, FMT_SAFE },
  { "socket_set_errmsg",       1, FMT_SAFE },
  { "ssl_set_errmsg",          1, FMT_SAFE },
  { "style_header",            1, FMT_HTML },

  { "style_set_current_page",  1, FMT_URL },
  { "style_submenu_element",   2, FMT_URL },
  { "style_submenu_sql",       3, FMT_SQL },
  { "webpage_error",           1, FMT_SAFE },
  { "xhref",                   2, FMT_URL },
};

Changes to src/main.c.

2268
2269
2270
2271
2272
2273
2274













2275
2276
2277
2278
2279
2280
2281
....
2453
2454
2455
2456
2457
2458
2459








2460
2461
2462
2463
2464
2465
2466
....
2482
2483
2484
2485
2486
2487
2488

2489
2490
2491
2492
2493
2494
2495
....
2714
2715
2716
2717
2718
2719
2720
2721
2722
2723
2724
2725
2726
2727
2728
2729
2730
2731
2732
2733
2734
      ** name of the subdirectory under the skins/ directory that holds
      ** the elements of the built-in skin.  If LABEL does not match,
      ** this directive is a silent no-op.
      */
      skin_use_alternative(blob_str(&value));
      blob_reset(&value);
      continue;













    }
    if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){
      /* cgi-debug: FILENAME
      **
      ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
      ** into FILENAME.  Useful for debugging CGI configuration problems.
      */
................................................................................
**   --baseurl URL    base URL (useful with reverse proxies)
**   --extroot DIR    document root for the /ext extension mechanism
**   --files GLOB     comma-separate glob patterns for static file to serve
**   --host NAME      specify hostname of the server
**   --https          signal a request coming in via https
**   --in FILE        Take input from FILE instead of standard input
**   --ipaddr ADDR    Assume the request comes from the given IP address








**   --localauth      enable automatic login for local connections
**   --nocompress     do not compress HTTP replies
**   --nodelay        omit backoffice processing if it would delay process exit
**   --nojail         drop root privilege but do not enter the chroot jail
**   --nossl          signal that no SSL connections are available
**   --notfound URL   use URL as "HTTP 404, object not found" page.
**   --out FILE       write results to FILE instead of to standard output
................................................................................
  const char *zInFile;
  const char *zOutFile;
  int useSCGI;
  int noJail;
  int allowRepoList;

  Th_InitTraceLog();


  /* The winhttp module passes the --files option as --files-urlenc with
  ** the argument being URL encoded, to avoid wildcard expansion in the
  ** shell.  This option is for internal use and is undocumented.
  */
  zFileGlob = find_option("files-urlenc",0,1);
  if( zFileGlob ){
................................................................................
**   --files GLOBLIST    Comma-separated list of glob patterns for static files
**   --localauth         enable automatic login for requests from localhost
**   --localhost         listen on 127.0.0.1 only (always true for "ui")
**   --https             Indicates that the input is coming through a reverse
**                       proxy that has already translated HTTPS into HTTP.
**   --jsmode MODE       Determine how javascript is delivered with pages.
**                       Mode can be one of:
**                          inline       JS inline at the end of the file
**                          inline-imm   JS inline at point of need
**                          sep          Separate HTTP requests for JS
**                          sep-imm      Separate HTTP requests each issued
**                                       at the need
**                          bundled      One single separate HTTP for all
**                                       JS resources
**   --max-latency N     Do not let any single HTTP request run for more than N
**                       seconds (only works on unix)
**   --nocompress        Do not compress HTTP replies
**   --nojail            Drop root privileges but do not enter the chroot jail
**   --nossl             signal that no SSL connections are available (Always
**                       set by default for the "ui" command)
**   --notfound URL      Redirect







>
>
>
>
>
>
>
>
>
>
>
>
>







 







>
>
>
>
>
>
>
>







 







>







 







|
|
|
<
|
|
|







2268
2269
2270
2271
2272
2273
2274
2275
2276
2277
2278
2279
2280
2281
2282
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294
....
2466
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478
2479
2480
2481
2482
2483
2484
2485
2486
2487
....
2503
2504
2505
2506
2507
2508
2509
2510
2511
2512
2513
2514
2515
2516
2517
....
2736
2737
2738
2739
2740
2741
2742
2743
2744
2745

2746
2747
2748
2749
2750
2751
2752
2753
2754
2755
      ** name of the subdirectory under the skins/ directory that holds
      ** the elements of the built-in skin.  If LABEL does not match,
      ** this directive is a silent no-op.
      */
      skin_use_alternative(blob_str(&value));
      blob_reset(&value);
      continue;
    }
    if( blob_eq(&key, "jsmode:") && blob_token(&line, &value) ){
      /* jsmode: MODE
      **
      ** Change how javascript resources are delivered with each HTML
      ** page.  MODE is "inline" to put all JS inline, or "separate" to
      ** cause each JS file to be requested using a separate HTTP request,
      ** or "bundled" to have all JS files to be fetched with a single
      ** auxiliary HTTP request.
      */
      builtin_set_js_delivery_mode(blob_str(&value),0);
      blob_reset(&value);
      continue;
    }
    if( blob_eq(&key, "cgi-debug:") && blob_token(&line, &value) ){
      /* cgi-debug: FILENAME
      **
      ** Causes output from cgi_debug() and CGIDEBUG(()) calls to go
      ** into FILENAME.  Useful for debugging CGI configuration problems.
      */
................................................................................
**   --baseurl URL    base URL (useful with reverse proxies)
**   --extroot DIR    document root for the /ext extension mechanism
**   --files GLOB     comma-separate glob patterns for static file to serve
**   --host NAME      specify hostname of the server
**   --https          signal a request coming in via https
**   --in FILE        Take input from FILE instead of standard input
**   --ipaddr ADDR    Assume the request comes from the given IP address
**   --jsmode MODE       Determine how javascript is delivered with pages.
**                       Mode can be one of:
**                          inline       All javascript is inserted inline at
**                                       the end of the HTML file.
**                          separate     Separate HTTP requests are made for
**                                       each javascript file.
**                          bundled      One single separate HTTP fetches all
**                                       javascript concatenated together.
**   --localauth      enable automatic login for local connections
**   --nocompress     do not compress HTTP replies
**   --nodelay        omit backoffice processing if it would delay process exit
**   --nojail         drop root privilege but do not enter the chroot jail
**   --nossl          signal that no SSL connections are available
**   --notfound URL   use URL as "HTTP 404, object not found" page.
**   --out FILE       write results to FILE instead of to standard output
................................................................................
  const char *zInFile;
  const char *zOutFile;
  int useSCGI;
  int noJail;
  int allowRepoList;

  Th_InitTraceLog();
  builtin_set_js_delivery_mode(find_option("jsmode",0,1),0);

  /* The winhttp module passes the --files option as --files-urlenc with
  ** the argument being URL encoded, to avoid wildcard expansion in the
  ** shell.  This option is for internal use and is undocumented.
  */
  zFileGlob = find_option("files-urlenc",0,1);
  if( zFileGlob ){
................................................................................
**   --files GLOBLIST    Comma-separated list of glob patterns for static files
**   --localauth         enable automatic login for requests from localhost
**   --localhost         listen on 127.0.0.1 only (always true for "ui")
**   --https             Indicates that the input is coming through a reverse
**                       proxy that has already translated HTTPS into HTTP.
**   --jsmode MODE       Determine how javascript is delivered with pages.
**                       Mode can be one of:
**                          inline       All javascript is inserted inline at
**                                       the end of the HTML file.
**                          separate     Separate HTTP requests are made for

**                                       each javascript file.
**                          bundled      One single separate HTTP fetches all
**                                       javascript concatenated together.
**   --max-latency N     Do not let any single HTTP request run for more than N
**                       seconds (only works on unix)
**   --nocompress        Do not compress HTTP replies
**   --nojail            Drop root privileges but do not enter the chroot jail
**   --nossl             signal that no SSL connections are available (Always
**                       set by default for the "ui" command)
**   --notfound URL      Redirect

Changes to src/style.c.

719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
    cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
    cgi_append_content("\n}\n", -1);
  }
  @ </script>
  builtin_fulfill_js_requests();
}

/*
** Extra JS to run after all content is loaded.
*/
void style_js_onload(const char *zFormat, ...){
  va_list ap;
  va_start(ap, zFormat);
  blob_vappendf(&blobOnLoad, zFormat, ap);
  va_end(ap);
}

/*
** Draw the footer at the bottom of the page.
*/
void style_footer(void){
  const char *zFooter;
  const char *zAd = 0;
  unsigned int mAdFlags = 0;







<
<
<
<
<
<
<
<
<
<







719
720
721
722
723
724
725










726
727
728
729
730
731
732
    cgi_append_content(blob_buffer(&blobOnLoad), blob_size(&blobOnLoad));
    cgi_append_content("\n}\n", -1);
  }
  @ </script>
  builtin_fulfill_js_requests();
}











/*
** Draw the footer at the bottom of the page.
*/
void style_footer(void){
  const char *zFooter;
  const char *zAd = 0;
  unsigned int mAdFlags = 0;