Multi-day accumulated fixes: tag dispatch, session/pooling correctness, SPA rollout, jetc compiler
JetCore engine (Tag.cpp/.h, Global.cpp/.h, __*.cpp tag classes): - Numerous __mysql.cpp connection-pooling correctness fixes (stale result sets, double-indirection sessionid bugs, field caching, pool keying) and a session-registration-before-connection-confirmed ordering fix (dangling pointer on a failed connect) - Tag.cpp: large body of fixes to the tag-dispatch/container-scanning logic (bare-name fallback, database aliasing, single-quote handling, @-prefix session variable resolution, TAGDEF caching, nested split-tag scanning for if/while/until/ifrow so an inner one doesn't corrupt an outer one's own boundary scan) plus the process-first rendering order fix (a <process> now runs before <checksession>/page resolution, fixing a real "blank page after successful login" bug) - Global.h/.cpp: added imapSessions (parallel to the existing __mysql* session map) for the new <imap> tag family - __whiledir.cpp/__include.cpp: caching and directory-name-aliasing fixes - __call.cpp/.h: fixed a dangling-pointer bug - __write.cpp: fixed an O_WRONLY-only open that couldn't create a new file - __ifrow.cpp/__sql.cpp: fixed the same sessionid double-indirection bug __mysql.cpp had (resolveKeyword's result was being used as a map key lookup instead of the resolved value itself) jetc compiler (jetc/JetParser.cpp/.h, JetCodegen.cpp/.h, JetAST.h, jetc.cpp, build-shared.sh, build-compiled.sh): - Parser fixes: inline <include>, nested-quote handling, void-tag recognition - Codegen fixes and expanded AST support - build-shared.sh: atomic rename into place for a freshly-built .jtc (a live server dlopen()ing the same path mid-rebuild was corrupting its own already-mapped view of the old file) and a staleness check so a cached JetCore .o doesn't silently keep serving yesterday's fixes forever - Added -lssl to both build scripts' link lines (needed once the new <imap> tag's client-side TLS code existed - previously nothing in this codebase used OpenSSL's SSL/TLS client API, only libcrypto) Site content (jetc/barant-site/): SPA (fetch-and-swap navigation) rollout across essentially every .page/.jet/.section/.tag/.proc/.method file - dynamic-content fixes, fragment-mode stripping, native $[@name] session variables replacing older mechanisms, and this session's own checkout.page redesign, login start-param redirect fix, and per-page side-menu (menu.bar/$[PAGE].menu) refresh support. Completed the earlier main.css/control.css move from assets/ to assets/images/ (git still showed the old paths as tracked-but-deleted until now). Deliberately left out of this commit: dozens of .pre-<description>- <date> manual backup files (this session's and earlier ones' own before/after snapshots, not meant for permanent history), compiled .jtc build outputs, ad hoc test binaries and scripts under jetc/ (login_asan, wcwc_test, optest2_bin, etc.), and jetc/__pycache__/ - none of these are meant to be tracked; a .gitignore covering them would be worth adding separately.
This commit is contained in:
1 parent
54b6e522f9
commit
b0cadc3f08
162 files changed
+3567
-2887
No files matched your search
+94
-29
@@ -9,36 +9,101 @@
|
||||
namespace jet {
|
||||
|
||||
__whiledir::__whiledir(coreutils::ZString &in, coreutils::MString &parentOut, Global &global, Tag *parent, Tag *local) : Tag(in, parentOut, global, parent, this) {
|
||||
if(!keywordDefined("path"))
|
||||
// Real 1.4 content (barantmusic.page/davidarant.page's own
|
||||
// bae1996.section) writes <whiledir dir="..." name="filename">,
|
||||
// not <whiledir path="..." filename="...">. Accept "dir" as an
|
||||
// alias for "path" and "name" as an alias for "filename" so that
|
||||
// content runs unmodified, matching the same "accept either"
|
||||
// precedent already used for <database name=>/<mysql database=>.
|
||||
// Resolved once into real local VALUES (not a dynamically-chosen
|
||||
// keyword NAME threaded through repeated keywordDefined()/
|
||||
// resolveKeyword() calls) - an earlier version of this fix passed
|
||||
// a ZString holding just the chosen attribute name around and hit
|
||||
// real, unexplained corruption (a whiledir on a real, correctly
|
||||
// specified directory resolved to a garbage nonsense path instead).
|
||||
// This form fixed it in isolation (a standalone whiledir_test.jet
|
||||
// against this exact directory/attributes works perfectly) but the
|
||||
// SAME garbage path still recurs when this exact content
|
||||
// (bae1996.section) is reached through real content's actual deep
|
||||
// <eval>/<dotag>/<include> nesting (40+ stack frames by that
|
||||
// point) - genuinely not yet root-caused; flagged in project
|
||||
// memory as still open. The try/catch below at least converts
|
||||
// whatever throws there into the same graceful, catchable error
|
||||
// page every other tag failure already gets, instead of a raw
|
||||
// std::exception unwinding past everything and dropping the
|
||||
// connection with no HTTP response at all.
|
||||
coreutils::MString dirPath;
|
||||
if(keywordDefined("path"))
|
||||
dirPath = resolveKeyword("path");
|
||||
else if(keywordDefined("dir"))
|
||||
dirPath = resolveKeyword("dir");
|
||||
else
|
||||
throw coreutils::Exception("whiledir tag must specify a path.");
|
||||
if(keywordDefined("sort") && (resolveKeyword("sort") == "true")) {
|
||||
std::vector<std::filesystem::directory_entry> entries;
|
||||
for(auto const &entry : std::filesystem::directory_iterator(resolveKeyword("path").str()))
|
||||
entries.push_back(entry);
|
||||
std::sort(entries.begin(), entries.end(), [](const auto &a, const auto &b) { return a.path() < b.path(); });
|
||||
for(const auto &entry : entries) {
|
||||
if(keywordDefined("fullpath"))
|
||||
global.variables[resolveKeyword("fullpath")] = entry.path();
|
||||
if(keywordDefined("filename"))
|
||||
global.variables[resolveKeyword("filename")] = entry.path().filename();
|
||||
if(keywordDefined("filenamenoextension"))
|
||||
global.variables[resolveKeyword("filenamenoextension")] = entry.path().stem();
|
||||
processContainer(container);
|
||||
container.reset();
|
||||
}
|
||||
} else {
|
||||
for(auto const &entry : std::filesystem::directory_iterator(variables[resolveKeyword("path")].str())) {
|
||||
if(keywordDefined("fullpath"))
|
||||
global.variables[resolveKeyword("fullpath")] = entry.path();
|
||||
if(keywordDefined("filename"))
|
||||
global.variables[resolveKeyword("filename")] = entry.path().filename();
|
||||
if(keywordDefined("filenamenoextension"))
|
||||
global.variables[resolveKeyword("filenamenoextension")] = entry.path().stem();
|
||||
processContainer(container);
|
||||
container.reset();
|
||||
}
|
||||
|
||||
// Every one of these attributes - which output variable name to
|
||||
// assign into for a given field, and whether that field was even
|
||||
// requested - is a static property of this <whiledir> invocation,
|
||||
// fixed at construction, never changing across its own loop. The
|
||||
// per-iteration body used to call keywordDefined()+resolveKeyword()
|
||||
// (2 map lookups each) for fullpath/filename/filenamenoextension
|
||||
// on every single directory entry - resolved once here instead,
|
||||
// same reasoning as __whilerow.cpp's session-pointer hoist.
|
||||
coreutils::MString filenameVarName;
|
||||
bool haveFilenameVar = false;
|
||||
if(keywordDefined("filename")) {
|
||||
filenameVarName = resolveKeyword("filename");
|
||||
haveFilenameVar = true;
|
||||
} else if(keywordDefined("name")) {
|
||||
filenameVarName = resolveKeyword("name");
|
||||
haveFilenameVar = true;
|
||||
}
|
||||
|
||||
|
||||
coreutils::MString fullpathVarName;
|
||||
bool haveFullpathVar = keywordDefined("fullpath");
|
||||
if(haveFullpathVar)
|
||||
fullpathVarName = resolveKeyword("fullpath");
|
||||
|
||||
coreutils::MString noExtVarName;
|
||||
bool haveNoExtVar = keywordDefined("filenamenoextension");
|
||||
if(haveNoExtVar)
|
||||
noExtVarName = resolveKeyword("filenamenoextension");
|
||||
|
||||
bool sorted = keywordDefined("sort") && (resolveKeyword("sort") == "true");
|
||||
|
||||
try {
|
||||
if(sorted) {
|
||||
std::vector<std::filesystem::directory_entry> entries;
|
||||
for(auto const &entry : std::filesystem::directory_iterator(dirPath.str()))
|
||||
entries.push_back(entry);
|
||||
std::sort(entries.begin(), entries.end(), [](const auto &a, const auto &b) { return a.path() < b.path(); });
|
||||
for(const auto &entry : entries) {
|
||||
if(haveFullpathVar)
|
||||
global.variables[fullpathVarName] = entry.path();
|
||||
if(haveFilenameVar)
|
||||
global.variables[filenameVarName] = entry.path().filename();
|
||||
if(haveNoExtVar)
|
||||
global.variables[noExtVarName] = entry.path().stem();
|
||||
processContainer(container);
|
||||
container.reset();
|
||||
}
|
||||
} else {
|
||||
for(auto const &entry : std::filesystem::directory_iterator(dirPath.str())) {
|
||||
if(haveFullpathVar)
|
||||
global.variables[fullpathVarName] = entry.path();
|
||||
if(haveFilenameVar)
|
||||
global.variables[filenameVarName] = entry.path().filename();
|
||||
if(haveNoExtVar)
|
||||
global.variables[noExtVarName] = entry.path().stem();
|
||||
processContainer(container);
|
||||
container.reset();
|
||||
}
|
||||
}
|
||||
} catch(std::exception &e) {
|
||||
coreutils::MString msg("whiledir failed: ");
|
||||
msg << e.what();
|
||||
throw coreutils::Exception(msg.str());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user