Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | The routines which emit fossil.XYZ.js modules now understand their dependencies, emit any deps in dependency order (recursively), and do not emit a given module more than once (simplifies usage and is an and overall improvement in cacheability). Added the pikchr click support to more pages. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA3-256: |
9b2b6f5b1cc695e52e89ae579850a427 |
User & Date: | stephan 2020-09-18 07:37:30 |
Context
2020-09-18
| ||
07:48 | Made the return code of a bit of new code match its docs. ... (check-in: 539eb61f user: stephan tags: trunk) | |
07:37 | The routines which emit fossil.XYZ.js modules now understand their dependencies, emit any deps in dependency order (recursively), and do not emit a given module more than once (simplifies usage and is an and overall improvement in cacheability). Added the pikchr click support to more pages. ... (check-in: 9b2b6f5b user: stephan tags: trunk) | |
05:07 | Minor C-side fossil JS API simplification to ease upcoming changes. ... (check-in: 58d86b16 user: stephan tags: trunk) | |
Changes
Changes to src/browse.c.
︙ | ︙ | |||
390 391 392 393 394 395 396 397 398 399 400 401 402 403 | @ </iframe> }else{ Blob content; const char *zMime = mimetype_from_name(zName); content_get(rid, &content); safe_html_context(DOCSRC_FILE); wiki_render_by_mimetype(&content, zMime); } } } db_finalize(&q); style_footer(); } | > | 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 | @ </iframe> }else{ Blob content; const char *zMime = mimetype_from_name(zName); content_get(rid, &content); safe_html_context(DOCSRC_FILE); wiki_render_by_mimetype(&content, zMime); document_emit_js(); } } } db_finalize(&q); style_footer(); } |
︙ | ︙ |
Changes to src/builtin.c.
︙ | ︙ | |||
660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 | style_script_end(); } /* The remaining window.fossil bootstrap code is not dependent on ** C-runtime state... */ builtin_request_js("fossil.bootstrap.js"); } } /* ** Convenience wrapper which calls builtin_request_js() for a series ** of builtin scripts named fossil.NAME.js. The first time it is ** called, it also calls builtin_emit_script_fossil_bootstrap() to ** initialize the window.fossil JS API. The first argument is the NAME ** part of the first API to emit. All subsequent arguments must be ** strings of the NAME part of additional fossil.NAME.js files, ** followed by a NULL argument to terminate the list. ** | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | > | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < < > > > > > > > > < | < | > | > > > | < < < < < < < < < < | < < > > > > > > > | 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 | style_script_end(); } /* The remaining window.fossil bootstrap code is not dependent on ** C-runtime state... */ builtin_request_js("fossil.bootstrap.js"); } } /* ** Given the NAME part of fossil.NAME.js, this function checks whether ** that module has been emitted by this function before. If it has, ** it returns -1 with no side effects. If it has not, it queues up ** (via builtin_request_js()) an emit of the module via and all of its ** known (by this function) fossil.XYZ.js dependencies (in their ** dependency order) and returns 1. If it does not find the given ** module name it returns 0. ** ** As a special case, if passed 0 then it queues up all known modules ** and returns -1. ** ** The very first time this is called, it unconditionally calls ** builtin_emit_script_fossil_bootstrap(). ** ** Any given module is only queued once, whether it is explicitly ** passed to the function or resolved as a dependency. Any attempts to ** re-queue them later are harmless no-ops. */ static int builtin_emit_fossil_js_once(const char * zName){ static int once = 0; int i; static struct FossilJs { const char * zName; /* NAME part of fossil.NAME.js */ int emitted; /* True if already emitted. */ const char * zDeps; /* \0-delimited list of other FossilJs ** entries: all known deps of this one. Each ** REQUIRES an EXPLICIT trailing \0, including ** the final one! */ } fjs[] = { /* This list ordering isn't strictly important. */ {"confirmer", 0, 0}, {"copybutton", 0, "dom\0"}, {"dom", 0, 0}, {"fetch", 0, 0}, {"numbered-lines", 0, "popupwidget\0copybutton\0"}, {"pikchr", 0, "dom\0"}, {"popupwidget", 0, "dom\0"}, {"storage", 0, 0}, {"tabs", 0, "dom\0"} }; const int nFjs = sizeof(fjs) / sizeof(fjs[0]); if(0==once){ ++once; builtin_emit_script_fossil_bootstrap(1); } if(0==zName){ for( i = 0; i < nFjs; ++i ){ builtin_emit_fossil_js_once(fjs[i].zName); } return 0; } for( i = 0; i < nFjs; ++i ){ if(0==strcmp(zName, fjs[i].zName)){ if(fjs[i].emitted){ return -1; }else{ char nameBuffer[50]; if(fjs[i].zDeps){ const char * zDep = fjs[i].zDeps; while(*zDep!=0){ builtin_emit_fossil_js_once(zDep); zDep += strlen(zDep)+1/*NUL delimiter*/; } } sqlite3_snprintf(sizeof(nameBuffer)-1, nameBuffer, "fossil.%s.js", fjs[i].zName); builtin_request_js(nameBuffer); fjs[i].emitted = 1; return 1; } } } return 0; } /* ** COMMAND: test-js-once ** ** Tester for builtin_emit_fossil_js_once(). ** ** Usage: %fossil test-js-once filename */ void test_js_once(void){ int i; if(g.argc<2){ usage("?FILENAME...?"); } if(2==g.argc){ builtin_emit_fossil_js_once(0); assert(builtin.nReq>8); }else{ for(i = 2; i < g.argc; ++i){ builtin_emit_fossil_js_once(g.argv[i]); } assert(builtin.nReq>1 && "don't forget implicit fossil.bootstrap.js"); } for(i = 0; i < builtin.nReq; ++i){ fossil_print("ndx#%d = %d = %s\n", i, builtin.aReq[i], aBuiltinFiles[builtin.aReq[i]].zName); } } /* ** Convenience wrapper which calls builtin_request_js() for a series ** of builtin scripts named fossil.NAME.js. The first time it is ** called, it also calls builtin_emit_script_fossil_bootstrap() to ** initialize the window.fossil JS API. The first argument is the NAME ** part of the first API to emit. All subsequent arguments must be ** strings of the NAME part of additional fossil.NAME.js files, ** followed by a NULL argument to terminate the list. ** ** e.g. pass it ("fetch", "dom", "tabs", 0) to load those 3 APIs (or ** pass it ("fetch","tabs",0), as "dom" is a dependency of "tabs", so ** it will be automatically loaded). Do not forget the trailing 0! ** ** If it is JS_BUNDLED then this routine queues up an emit of ALL of ** the JS fossil.XYZ.js APIs which are not strictly specific to a ** single page, and then calls builtin_fulfill_js_requests(). The idea ** is that we can get better bundle caching and reduced HTTP requests ** by including all JS, rather than creating separate bundles on a ** per-page basis. In this case, all arguments are ignored! ** ** This function has an internal mapping of the dependencies for each ** of the known fossil.XYZ.js modules and ensures that the ** dependencies also get queued (recursively) and that each module is ** queued only once. ** ** If passed a name which is not a base fossil module name then it ** will fail fatally! ** ** DO NOT use this for loading fossil.page.*.js: use ** builtin_request_js() for those. ** ** If the current JS delivery mode is *not* JS_BUNDLED then this ** function queues up a request for each given module and its known ** dependencies, but does not immediately fulfill the request, thus it ** can be called multiple times. ** ** If a given module is ever passed to this more than once, either in ** a single invocation or multiples, it is only queued for emit a ** single time (i.e. the 2nd and subsequent ones become ** no-ops). Likewise, if a module is requested but was already ** automatically queued to fulfill a dependency, the explicit request ** becomes a no-op. ** ** Bundled mode is the only mode in which this API greatly improves ** aggregate over-the-wire and HTTP request costs. For other modes, ** reducing the inclusion of fossil.XYZ APIs to their bare minimum ** provides the lowest aggregate costs. For debate and details, see ** the discussion at: ** ** https://fossil-scm.org/forum/forumpost/3fa2633f3e ** ** In practice it is normally necessary (or preferred) to call ** builtin_fulfill_js_requests() after calling this, before proceeding ** to call builtin_request_js() for page-specific JS, in order to ** improve cachability. ** ** Minor caveat: the purpose of emitting all of the fossil.XYZ JS APIs ** at once is to reduce over-the-wire transfers by enabling cross-page ** caching, but if there are other JS scripts pending via ** builtin_request_js() when this is called then they will be included ** in the JS request emitted by this routine, resulting in a different ** script URL than if they were not included. Thus, if a given page ** has its own scripts to install via builtin_request_js(), they ** should, if possible, be delayed until after this is called OR the ** page should call builtin_fulfill_js_requests() to flush the request ** queue before calling this routine. ** ** Achtung: the fossil.page.XYZ.js files are page-specific, containing ** the app-level logic for that specific page, and loading more than ** one of them in a single page will break that page. Each of those ** expects to "own" the page it is loaded in, and it should be loaded ** as late in the JS-loading process as feasible, ideally bundled (via ** builtin_request_js()) with any other app-/page-specific JS it may ** need. ** ** Example usage: ** ** builtin_fossil_js_bundle_or("dom", "fetch", 0); ** ** In bundled mode, that will (the first time it is called) emit all ** builtin fossil JS APIs and "fulfill" the queue immediately. In ** non-bundled mode it will queue up the "dom" and "fetch" APIs to be ** emitted the next time builtin_fulfill_js_requests() is called. */ void builtin_fossil_js_bundle_or( const char * zApi, ... ) { static int bundled = 0; const char *zArg; va_list vargs; if(JS_BUNDLED == builtin_get_js_delivery_mode()){ if(!bundled){ bundled = 1; builtin_emit_fossil_js_once(0); builtin_fulfill_js_requests(); } return; } va_start(vargs,zApi); for( zArg = zApi; zArg!=0; (zArg = va_arg (vargs, const char *))){ if(0==builtin_emit_fossil_js_once(zArg)){ fossil_fatal("Unknown fossil JS module: %s\n", zArg); } } va_end(vargs); } |
Changes to src/doc.c.
︙ | ︙ | |||
399 400 401 402 403 404 405 | } return 0; } /* ** Emit Javascript which applies (or optionally can apply) to both the ** /doc and /wiki pages. None of this implements required | | > > > | | | | | | > | 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 | } return 0; } /* ** Emit Javascript which applies (or optionally can apply) to both the ** /doc and /wiki pages. None of this implements required ** functionality, just nice-to-haves. Any calls after the first are ** no-ops. */ void document_emit_js(void){ static int once = 0; if(0==once++){ builtin_fossil_js_bundle_or("pikchr", 0); style_script_begin(__FILE__,__LINE__); CX("window.addEventListener('load', " "()=>window.fossil.pikchr.addSrcView(), " "false);\n"); style_script_end(); } } /* ** Guess the mime-type of a document based on its name. */ const char *mimetype_from_name(const char *zName){ const char *z; |
︙ | ︙ |
Changes to src/event.c.
︙ | ︙ | |||
226 227 228 229 230 231 232 233 234 235 236 237 238 239 | @ </pre> } zFullId = db_text(0, "SELECT SUBSTR(tagname,7)" " FROM tag" " WHERE tagname GLOB 'event-%q*'", zId); attachment_list(zFullId, "<hr /><h2>Attachments:</h2><ul>"); style_footer(); manifest_destroy(pTNote); } /* ** Add or update a new tech note to the repository. rid is id of ** the prior version of this technote, if any. | > | 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 | @ </pre> } zFullId = db_text(0, "SELECT SUBSTR(tagname,7)" " FROM tag" " WHERE tagname GLOB 'event-%q*'", zId); attachment_list(zFullId, "<hr /><h2>Attachments:</h2><ul>"); document_emit_js(); style_footer(); manifest_destroy(pTNote); } /* ** Add or update a new tech note to the repository. rid is id of ** the prior version of this technote, if any. |
︙ | ︙ |
Changes to src/forum.c.
︙ | ︙ | |||
740 741 742 743 744 745 746 | /* ** Emit Forum Javascript which applies (or optionally can apply) ** to all forum-related pages. It does not include page-specific ** code (e.g. "forum.js"). */ static void forum_emit_js(void){ | | | | 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 | /* ** Emit Forum Javascript which applies (or optionally can apply) ** to all forum-related pages. It does not include page-specific ** code (e.g. "forum.js"). */ static void forum_emit_js(void){ builtin_fossil_js_bundle_or("copybutton", "pikchr", 0); builtin_request_js("fossil.page.forumpost.js"); } /* ** WEBPAGE: forumpost ** ** Show a single forum posting. The posting is shown in context with ** its entire thread. The selected posting is enclosed within |
︙ | ︙ |
Changes to src/fuzz.c.
︙ | ︙ | |||
24 25 26 27 28 29 30 | ** ./configure ** ** Then edit the Makefile as follows: ** ** (1) Change CC to be "clang-6.0" or some other compiler that ** supports libFuzzer ** | | | 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | ** ./configure ** ** Then edit the Makefile as follows: ** ** (1) Change CC to be "clang-6.0" or some other compiler that ** supports libFuzzer ** ** (2) Change APPNAME to "fossil-fuzz" ** ** (3) Add "-fsanitize=fuzzer" and "-DFOSSIL_FUZZ" to TCCFLAGS. Perhaps ** make the first change "-fsanitize=fuzzer,undefined,address" for ** extra, but slower, testing. ** ** Then build the fuzzer using: ** |
︙ | ︙ |
Changes to src/info.c.
︙ | ︙ | |||
1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 | @ <div class="section">Content</div> blob_init(&wiki, pWiki->zWiki, -1); safe_html_context(DOCSRC_WIKI); wiki_render_by_mimetype(&wiki, pWiki->zMimetype); blob_reset(&wiki); manifest_destroy(pWiki); style_footer(); } /* ** Find an check-in based on query parameter zParam and parse its ** manifest. Return the number of errors. */ | > | 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 | @ <div class="section">Content</div> blob_init(&wiki, pWiki->zWiki, -1); safe_html_context(DOCSRC_WIKI); wiki_render_by_mimetype(&wiki, pWiki->zMimetype); blob_reset(&wiki); manifest_destroy(pWiki); document_emit_js(); style_footer(); } /* ** Find an check-in based on query parameter zParam and parse its ** manifest. Return the number of errors. */ |
︙ | ︙ | |||
2127 2128 2129 2130 2131 2132 2133 | cgi_printf("%z", htmlize(z, nZ)); CX("</code></pre></td></tr></tbody></table>\n"); if(includeJS && !emittedJS){ emittedJS = 1; if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){ builtin_request_js("scroll.js"); } | | < | 2128 2129 2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 | cgi_printf("%z", htmlize(z, nZ)); CX("</code></pre></td></tr></tbody></table>\n"); if(includeJS && !emittedJS){ emittedJS = 1; if( db_int(0, "SELECT EXISTS(SELECT 1 FROM lnos)") ){ builtin_request_js("scroll.js"); } builtin_fossil_js_bundle_or("numbered-lines", 0); } } /* ** COMMAND: test-line-numbers ** ** Usage: %fossil test-line-numbers FILE ?LN-SPEC? |
︙ | ︙ | |||
2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 | style_submenu_element("Content", "%R/artifact/%s", zUuid); }else{ @ <hr /> content_get(rid, &content); if( renderAsWiki ){ safe_html_context(DOCSRC_FILE); wiki_render_by_mimetype(&content, zMime); }else if( renderAsHtml ){ @ <iframe src="%R/raw/%s(zUuid)" @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" @ sandbox="allow-same-origin" id="ifm1"> @ </iframe> @ <script nonce="%h(style_nonce())">/* info.c:%d(__LINE__) */ @ document.getElementById("ifm1").addEventListener("load", | > | 2435 2436 2437 2438 2439 2440 2441 2442 2443 2444 2445 2446 2447 2448 2449 | style_submenu_element("Content", "%R/artifact/%s", zUuid); }else{ @ <hr /> content_get(rid, &content); if( renderAsWiki ){ safe_html_context(DOCSRC_FILE); wiki_render_by_mimetype(&content, zMime); document_emit_js(); }else if( renderAsHtml ){ @ <iframe src="%R/raw/%s(zUuid)" @ width="100%%" frameborder="0" marginwidth="0" marginheight="0" @ sandbox="allow-same-origin" id="ifm1"> @ </iframe> @ <script nonce="%h(style_nonce())">/* info.c:%d(__LINE__) */ @ document.getElementById("ifm1").addEventListener("load", |
︙ | ︙ |
Changes to src/pikchrshow.c.
︙ | ︙ | |||
355 356 357 358 359 360 361 | Blob out = empty_blob; pikchr_process(zContent, pikFlags, 0, &out); CX("%b", &out); blob_reset(&out); } CX("</div>"/*#pikchrshow-output*/); } CX("</fieldset>"/*#pikchrshow-output-wrapper*/); } CX("</div>"/*sbs-wrapper*/); | | | | | 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 | Blob out = empty_blob; pikchr_process(zContent, pikFlags, 0, &out); CX("%b", &out); blob_reset(&out); } CX("</div>"/*#pikchrshow-output*/); } CX("</fieldset>"/*#pikchrshow-output-wrapper*/); } CX("</div>"/*sbs-wrapper*/); builtin_fossil_js_bundle_or("fetch", "copybutton", "popupwidget", "storage", "pikchr", 0); builtin_request_js("fossil.page.pikchrshow.js"); builtin_fulfill_js_requests(); style_footer(); } /* ** COMMAND: pikchr* ** |
︙ | ︙ |
Changes to src/timeline.c.
︙ | ︙ | |||
2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 | } www_print_timeline(&q, tmFlags, zThisUser, zThisTag, zBrName, selectedRid, secondaryRid, 0); db_finalize(&q); if( zOlderButton ){ @ %z(chref("button","%z",zOlderButton))More ↓</a> } style_footer(); } /* ** The input query q selects various records. Print a human-readable ** summary of those records. ** | > | 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 | } www_print_timeline(&q, tmFlags, zThisUser, zThisTag, zBrName, selectedRid, secondaryRid, 0); db_finalize(&q); if( zOlderButton ){ @ %z(chref("button","%z",zOlderButton))More ↓</a> } document_emit_js(/*handles pikchrs rendered above*/); style_footer(); } /* ** The input query q selects various records. Print a human-readable ** summary of those records. ** |
︙ | ︙ |