| | @@ -1425,20 +1425,28 @@ |
| 1425 | 1425 | } |
| 1426 | 1426 | |
| 1427 | 1427 | /* |
| 1428 | 1428 | ** The first time this is called, it emits code to install and |
| 1429 | 1429 | ** bootstrap the window.fossil object, using the built-in file |
| 1430 | | -** fossil.bootstrap.js (not to be confused with bootstrap.js). It does |
| 1431 | | -** NOT wrap that in a script tag because it's called from |
| 1432 | | -** style_emit_script_tag(). |
| 1430 | +** fossil.bootstrap.js (not to be confused with bootstrap.js). |
| 1433 | 1431 | ** |
| 1434 | 1432 | ** Subsequent calls are no-ops. |
| 1433 | +** |
| 1434 | +** If passed a true value, it emits the contents directly to the page |
| 1435 | +** output, else it emits a script tag with a src=builtin/... to load |
| 1436 | +** the script. It always outputs a small pre-bootstrap element in its |
| 1437 | +** own script tag to initialize parts which need C-runtime-level |
| 1438 | +** information, because loading the main fossil.bootstrap.js either |
| 1439 | +** inline or via a <script src=...>, as specified by the first |
| 1440 | +** argument. |
| 1435 | 1441 | */ |
| 1436 | | -static void style_emit_script_fossil_bootstrap(){ |
| 1442 | +void style_emit_script_fossil_bootstrap(int asInline){ |
| 1437 | 1443 | static int once = 0; |
| 1438 | 1444 | if(0==once++){ |
| 1439 | | - /* Set up the generic/app-agnostic parts of window.fossil */ |
| 1445 | + /* Set up the generic/app-agnostic parts of window.fossil |
| 1446 | + ** which require C-level state... */ |
| 1447 | + style_emit_script_tag(0,0); |
| 1440 | 1448 | CX("(function(){\n" |
| 1441 | 1449 | "if(!window.fossil) window.fossil={};\n" |
| 1442 | 1450 | "window.fossil.version = \"%j\";\n" |
| 1443 | 1451 | /* fossil.rootPath is the top-most CGI/server path, |
| 1444 | 1452 | including a trailing slash. */ |
| | @@ -1450,137 +1458,121 @@ |
| 1450 | 1458 | ** own page-specific state. |
| 1451 | 1459 | */ |
| 1452 | 1460 | CX("window.fossil.page = {" |
| 1453 | 1461 | "page:\"%T\"" |
| 1454 | 1462 | "};\n", g.zPath); |
| 1463 | + CX("})();\n"); |
| 1455 | 1464 | /* The remaining code is not dependent on C-runtime state... */ |
| 1456 | | - CX("%s\n", builtin_text("fossil.bootstrap.js")); |
| 1457 | | - CX("})();\n"); |
| 1465 | + if(asInline){ |
| 1466 | + CX("%s\n", builtin_text("fossil.bootstrap.js")); |
| 1467 | + } |
| 1468 | + style_emit_script_tag(1,0); |
| 1469 | + if(asInline==0){ |
| 1470 | + style_emit_script_tag(0,"builtin/fossil.bootstrap.js"); |
| 1471 | + } |
| 1458 | 1472 | } |
| 1459 | 1473 | } |
| 1460 | 1474 | |
| 1461 | 1475 | /* |
| 1462 | | -** If passed 0, it emits a script opener tag with this request's |
| 1463 | | -** nonce. If passed non-0 it emits a script closing tag. |
| 1476 | +** If passed 0 as its first argument, it emits a script opener tag |
| 1477 | +** with this request's nonce. If passed non-0 it emits a script |
| 1478 | +** closing tag. Mnemonic for remembering the order in which to pass 0 |
| 1479 | +** or 1 as the first argument to this function: 0 comes before 1. |
| 1480 | +** |
| 1481 | +** If passed 0 as its first argument and a non-NULL/non-empty zSrc, |
| 1482 | +** then it instead emits: |
| 1483 | +** |
| 1484 | +** <script src='%R/{{zSrc}}'></script> |
| 1485 | +** |
| 1486 | +** zSrc is always assumed to be a repository-relative path without |
| 1487 | +** a leading slash, and has %R/ prepended to it. |
| 1464 | 1488 | ** |
| 1465 | | -** The very first time it is called, it emits some bootstrapping JS |
| 1466 | | -** code immediately after the script opener. Specifically, it defines |
| 1467 | | -** window.fossil if it's not already defined, and sets up its most |
| 1468 | | -** basic functionality. |
| 1489 | +** Meaning that no follow-up call to pass a non-0 first argument |
| 1490 | +** to close the tag. zSrc is ignored if the first argument is not |
| 1491 | +** 0. |
| 1492 | +** |
| 1469 | 1493 | */ |
| 1470 | | -void style_emit_script_tag(int phase){ |
| 1471 | | - static int once = 0; |
| 1472 | | - if(0==phase){ |
| 1473 | | - CX("<script nonce='%s'>", style_nonce()); |
| 1474 | | - if(0==once++){ |
| 1475 | | - style_emit_script_fossil_bootstrap(); |
| 1494 | +void style_emit_script_tag(int isCloser, const char * zSrc){ |
| 1495 | + if(0==isCloser){ |
| 1496 | + if(zSrc!=0 && zSrc[0]!=0){ |
| 1497 | + CX("<script src='%R/%T'></script>\n", zSrc); |
| 1498 | + }else{ |
| 1499 | + CX("<script nonce='%s'>", style_nonce()); |
| 1476 | 1500 | } |
| 1477 | 1501 | }else{ |
| 1478 | 1502 | CX("</script>\n"); |
| 1479 | 1503 | } |
| 1480 | 1504 | } |
| 1481 | 1505 | |
| 1482 | 1506 | /* |
| 1483 | | -** Emits the text of builtin_text(zName), which is assumed to be |
| 1484 | | -** JavaScript code, and wrapps that in a pair of calls to |
| 1485 | | -** style_emit_script_tag(). |
| 1507 | +** Emits a script tag which uses content from a builtin script file. |
| 1508 | +** |
| 1509 | +** If asInline is true, it is emitted directly as an opening tag, the |
| 1510 | +** content of the zName builtin file, and a closing tag. If it is false, |
| 1511 | +** a script tag loading it via src=builtin/{{zName}} is emitted. |
| 1486 | 1512 | */ |
| 1487 | | -void style_emit_script_builtin(char const * zName){ |
| 1488 | | - style_emit_script_tag(0); |
| 1513 | +void style_emit_script_builtin(char const * zName, int asInline){ |
| 1514 | + if(asInline){ |
| 1515 | + style_emit_script_tag(0,0); |
| 1489 | 1516 | CX("%s", builtin_text(zName)); |
| 1490 | | - style_emit_script_tag(1); |
| 1517 | + style_emit_script_tag(1,0); |
| 1518 | + }else{ |
| 1519 | + char * zFull = mprintf("builtin/%s",zName); |
| 1520 | + style_emit_script_tag(0,zFull); |
| 1521 | + fossil_free(zFull); |
| 1522 | + } |
| 1491 | 1523 | } |
| 1492 | 1524 | |
| 1493 | 1525 | /* |
| 1494 | | -** The first time this is called, it emits a JS script block, |
| 1495 | | -** including tags, using the contents of the built-in file |
| 1496 | | -** fossil.fetch.js, which defines window.fossil.fetch(), an HTTP |
| 1497 | | -** request/response mini-framework similar (but not identical) to the |
| 1498 | | -** not-quite-ubiquitous window.fetch(). It calls |
| 1499 | | -** style_emit_script_tag(), which may inject other JS bootstrapping |
| 1500 | | -** bits. Subsequent calls are no-ops. |
| 1501 | | -** |
| 1502 | | -** JS usages: |
| 1503 | | -** |
| 1504 | | -** fossil.fetch( URI [, onLoadCallback] ); |
| 1505 | | -** |
| 1506 | | -** fossil.fetch( URI [, optionsObject = {}] ); |
| 1507 | | -** |
| 1508 | | -** Noting that URI must be relative to the top of the repository and |
| 1509 | | -** should not start with a slash (if it does, it is stripped). It gets |
| 1510 | | -** the equivalent of "%R/" prepended to it. |
| 1511 | | -** |
| 1512 | | -** The optionsObject may be an onload callback or an object with any |
| 1513 | | -** of these properties: |
| 1514 | | -** |
| 1515 | | -** - onload: callback(responseData) (default = output response to |
| 1516 | | -** the console). |
| 1517 | | -** |
| 1518 | | -** - onerror: callback(XHR onload event | exception) |
| 1519 | | -** (default = event or exception to the console). |
| 1520 | | -** |
| 1521 | | -** - method: 'POST' | 'GET' (default = 'GET') |
| 1522 | | -** |
| 1523 | | -** - payload: anything acceptable by XHR2.send(ARG) (DOMString, |
| 1524 | | -** Document, FormData, Blob, File, ArrayBuffer), or a plain object |
| 1525 | | -** or array, either of which gets JSON.stringify()'d. If payload is |
| 1526 | | -** set then the method is automatically set to 'POST'. If an |
| 1527 | | -** object/array is converted to JSON, the contentType option is |
| 1528 | | -** automatically set to 'application/json'. By default XHR2 will set |
| 1529 | | -** the content type based on the payload type. |
| 1530 | | -** |
| 1531 | | -** - contentType: Optional request content type when POSTing. Ignored |
| 1532 | | -** if the method is not 'POST'. |
| 1533 | | -** |
| 1534 | | -** - responseType: optional string. One of ("text", "arraybuffer", |
| 1535 | | -** "blob", or "document") (as specified by XHR2). Default = "text". |
| 1536 | | -** As an extension, it supports "json", which tells it that the |
| 1537 | | -** response is expected to be text and that it should be |
| 1538 | | -** JSON.parse()d before passing it on to the onload() callback. |
| 1539 | | -** |
| 1540 | | -** - urlParams: string|object. If a string, it is assumed to be a |
| 1541 | | -** URI-encoded list of params in the form "key1=val1&key2=val2...", |
| 1542 | | -** with NO leading '?'. If it is an object, all of its properties |
| 1543 | | -** get converted to that form. Either way, the parameters get |
| 1544 | | -** appended to the URL before submitting the request. |
| 1545 | | -** |
| 1546 | | -** When an options object does not provide onload() or onerror() |
| 1547 | | -** handlers of its own, this function falls back to |
| 1548 | | -** fossil.fetch.onload() and fossil.fetch.onerror() as defaults. The |
| 1549 | | -** default implementations route the data through the dev console and |
| 1550 | | -** (for onerror()) through fossil.error(). Individual pages may |
| 1551 | | -** overwrite those members to provide default implementations suitable |
| 1552 | | -** for the page's use. |
| 1553 | | -** |
| 1554 | | -** Returns this object, noting that the XHR request is asynchronous, |
| 1555 | | -** and still in transit (or has yet to be sent) when that happens. |
| 1556 | | -*/ |
| 1557 | | -void style_emit_script_fetch(){ |
| 1526 | +** The first time this is called, it emits the JS code from the |
| 1527 | +** built-in file fossil.fossil.js. Subsequent calls are no-ops. |
| 1528 | +** |
| 1529 | +** If passed a true value, it emits the contents directly |
| 1530 | +** to the page output, else it emits a script tag with a |
| 1531 | +** src=builtin/... to load the script. |
| 1532 | +** |
| 1533 | +** Note that this code relies on that loaded via |
| 1534 | +** style_emit_script_fossil_bootstrap() but it does not call that |
| 1535 | +** routine. |
| 1536 | +*/ |
| 1537 | +void style_emit_script_fetch(int asInline){ |
| 1558 | 1538 | static int once = 0; |
| 1559 | 1539 | if(0==once++){ |
| 1560 | | - style_emit_script_builtin("fossil.fetch.js"); |
| 1540 | + style_emit_script_builtin("fossil.fetch.js", asInline); |
| 1561 | 1541 | } |
| 1562 | 1542 | } |
| 1563 | 1543 | |
| 1564 | 1544 | /* |
| 1565 | 1545 | ** The first time this is called, it emits the JS code from the |
| 1566 | 1546 | ** built-in file fossil.dom.js. Subsequent calls are no-ops. |
| 1547 | +** |
| 1548 | +** If passed a true value, it emits the contents directly |
| 1549 | +** to the page output, else it emits a script tag with a |
| 1550 | +** src=builtin/... to load the script. |
| 1551 | +** |
| 1552 | +** Note that this code relies on that loaded via |
| 1553 | +** style_emit_script_fossil_bootstrap(), but it does not call that |
| 1554 | +** routine. |
| 1567 | 1555 | */ |
| 1568 | | -void style_emit_script_dom(){ |
| 1556 | +void style_emit_script_dom(int asInline){ |
| 1569 | 1557 | static int once = 0; |
| 1570 | 1558 | if(0==once++){ |
| 1571 | | - style_emit_script_builtin("fossil.dom.js"); |
| 1559 | + style_emit_script_builtin("fossil.dom.js", asInline); |
| 1572 | 1560 | } |
| 1573 | 1561 | } |
| 1574 | 1562 | |
| 1575 | 1563 | /* |
| 1576 | | -** The first time this is called, it calls style_emit_script_dom() and |
| 1577 | | -** emits the JS code from the built-in file fossil.tabs.js. |
| 1578 | | -** Subsequent calls are no-ops. |
| 1564 | +** The first time this is called, it calls style_emit_script_dom(), |
| 1565 | +** passing it the given asInline value, and emits the JS code from the |
| 1566 | +** built-in file fossil.tabs.js. Subsequent calls are no-ops. |
| 1567 | +** |
| 1568 | +** If passed a true value, it emits the contents directly |
| 1569 | +** to the page output, else it emits a script tag with a |
| 1570 | +** src=builtin/... to load the script. |
| 1579 | 1571 | */ |
| 1580 | | -void style_emit_script_tabs(){ |
| 1572 | +void style_emit_script_tabs(int asInline){ |
| 1581 | 1573 | static int once = 0; |
| 1582 | 1574 | if(0==once++){ |
| 1583 | | - style_emit_script_dom(); |
| 1584 | | - style_emit_script_builtin("fossil.tabs.js"); |
| 1575 | + style_emit_script_dom(asInline); |
| 1576 | + style_emit_script_builtin("fossil.tabs.js",asInline); |
| 1585 | 1577 | } |
| 1586 | 1578 | } |
| 1587 | 1579 | |