Compare commits

..

4 Commits

Author SHA1 Message Date
ee25b79fb5 added basic filter tests...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2026-07-25 17:22:04 +03:00
c3523fe9b4 removed stray .wait when there is nothing to wait for...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2026-07-25 17:01:05 +03:00
c411414212 filters still buggy...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2026-07-25 01:56:54 +03:00
af53fe30b4 cleanup...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2026-07-25 01:49:31 +03:00
2 changed files with 69 additions and 62 deletions

View File

@ -647,7 +647,6 @@ module.BaseParser = {
&& (body = this.expand(page, body, state, nested_handlers)) && (body = this.expand(page, body, state, nested_handlers))
// call macro... // call macro...
//* XXX LOCAL_STATE
// NOTE: here we separate local macro state and global/parent // NOTE: here we separate local macro state and global/parent
// state via the prototpype... // state via the prototpype...
// This is mainly needed to sparate promises, since the // This is mainly needed to sparate promises, since the
@ -655,7 +654,8 @@ module.BaseParser = {
// each macro can wait async for an arbitrary amount of // each macro can wait async for an arbitrary amount of
// time it only should care about what was promised // time it only should care about what was promised
// before it neglecting what came after. // before it neglecting what came after.
var res = that.callMacro(page, name, args, body, { var res =
that.callMacro(page, name, args, body, {
// global/parent state... // global/parent state...
__proto__: state, __proto__: state,
root: state.root ?? state, root: state.root ?? state,
@ -664,9 +664,6 @@ module.BaseParser = {
waitAll: state.waitAll, waitAll: state.waitAll,
waitNested: state.waitNested, waitNested: state.waitNested,
}) })
/*/
var res = that.callMacro(page, name, args, body, state)
//*/
// async... // async...
if(res instanceof Promise){ if(res instanceof Promise){
@ -793,8 +790,6 @@ module.BaseParser = {
ast ast
: ast.iter() : ast.iter()
// XXX LOCAL_STATE
//state.unresolved = []
var unresolved = [] var unresolved = []
// merge resolved elements into the last item of elems... // merge resolved elements into the last item of elems...
@ -838,9 +833,6 @@ module.BaseParser = {
// nested macro with no value set -- skip... // nested macro with no value set -- skip...
if(that.macros[elem.name] instanceof Array){ if(that.macros[elem.name] instanceof Array){
continue } continue }
// XXX LOCAL_STATE...
// ...use the same mechanism here as in .expand(..)
//state.unresolved
unresolved unresolved
.push(elem.resolving instanceof Promise ? .push(elem.resolving instanceof Promise ?
elem.resolving elem.resolving
@ -850,13 +842,14 @@ module.BaseParser = {
// are the responsibility of the respective macros... // are the responsibility of the respective macros...
elems.push(elem) } elems.push(elem) }
var resolving = if(unresolved.length > 0){
state.wait = var resolving =
Promise.all([state.wait, ...unresolved]) state.wait =
// cleanup... Promise.all([state.wait, ...unresolved])
.then(function(){ // cleanup...
if(state.wait === resolving){ .then(function(){
delete state.wait } }) if(state.wait === resolving){
delete state.wait } }) }
return elems }, return elems },
@ -879,10 +872,12 @@ module.BaseParser = {
// - apply stage III post handlers // - apply stage III post handlers
// //
// //
// XXX BUG: this seems to always return a promise...
// XXX RECURSION might be a good idea to limit recursion/nesting depth // XXX RECURSION might be a good idea to limit recursion/nesting depth
// of inner resolve(..)... // of inner resolve(..)...
// XXX RENAME... // XXX RENAME...
finalize: function(page, ast, state={}, nested_handlers={}, wait='wait'){ finalize: function(page, ast, state={}, nested_handlers={}, wait='wait'){
//finalize: function(page, ast, state={}, nested_handlers={}, wait='waitNested'){
var that = this var that = this
var stage3 = function(ast){ var stage3 = function(ast){
@ -895,7 +890,6 @@ module.BaseParser = {
var resolve = function(ast){ var resolve = function(ast){
return Promise.awaitOrRun( return Promise.awaitOrRun(
// XXX LOCAL_STATE // XXX LOCAL_STATE
//...(state.unresolved ?? []),
state.hasOwnProperty('wait') ? state.hasOwnProperty('wait') ?
state.wait state.wait
// XXX // XXX
@ -921,7 +915,7 @@ module.BaseParser = {
// XXX do we actually need to wait here??? // XXX do we actually need to wait here???
// ...each macro should already be waiting... // ...each macro should already be waiting...
//...[state[wait]].flat(), //...[state[wait]].flat(),
state.hasOwnProperty(wait) ? (wait && state.hasOwnProperty(wait)) ?
state[wait] state[wait]
: null, : null,
function(){ function(){
@ -931,12 +925,9 @@ module.BaseParser = {
return Promise.awaitOrRun( return Promise.awaitOrRun(
// XXX LOCAL_STATE if we are nested we should not wait // XXX LOCAL_STATE if we are nested we should not wait
// for anything after the caller... // for anything after the caller...
//(state.unresolved that.isResolved(ast) ?
// || !that.isResolved(ast)) ? ast
//state.hasOwnProperty('wait') ? : resolve(ast),
!that.isResolved(ast) ?
resolve(ast)
: ast,
function(ast){ function(ast){
return ( return (
// stage III post... // stage III post...
@ -953,16 +944,8 @@ module.BaseParser = {
function(res){ function(res){
return res.join('') }) }, return res.join('') }) },
// XXX
execNested: function(page, ast, state={}, nested_handlers={}){ execNested: function(page, ast, state={}, nested_handlers={}){
//return ast
/* XXX LOCAL_STATE waitNested here deadlocks the parser -- not sure why...
//return this.exec(page, ast, state, nested_handlers, 'unresolved') },
return this.exec(page, ast, state, nested_handlers, 'waitNested') }, return this.exec(page, ast, state, nested_handlers, 'waitNested') },
/*/
return this.exec(page, ast, state, nested_handlers, '') },
//*/
// XXX render api... // XXX render api...
@ -1047,20 +1030,7 @@ module.parser = {
echo: function(page, args, body, state){ echo: function(page, args, body, state){
console.log(['----', ...Object.keys(args), body ?? ''].join(' ').gray) console.log(['----', ...Object.keys(args), body ?? ''].join(' ').gray)
return Promise.awaitOrRun( return Promise.awaitOrRun(
// XXX this works and sequences correctly...
state.waitNested, state.waitNested,
// XXX this deadlocks...
// calling .execNested(..) from any macro (@include(..)
// in the example code) will deadlock the execution
// if .execNested(..) is waiting for .waitNested...
// to reproduce:
// - uncomment the LOCAL_STATE track
// - run:
// @echo(A)@source(/async/echo)@echo(B)@include(/async/echo)@echo(C)
// -> need a way to call .exex(..) while evaluating...
//this.execNested(page, '', state),
// XXX this also does not work...
//this.resolve(page, '', state),
function(){ function(){
console.log(' --', ...Object.keys(args), body ?? '') }) }, console.log(' --', ...Object.keys(args), body ?? '') }) },
//*/ //*/
@ -1110,18 +1080,16 @@ module.parser = {
// stage III // stage III
return function(state){ return function(state){
return Promise.awaitOrRun( return Promise.awaitOrRun(
// apply the filters... // apply the filters...
that.finalize( that.finalize(
page, page,
body, body,
{ {
...state, __proto__: state,
filters: clear ? filters: clear ?
filters filters
: [...filters, ...state.filters ?? []], : [...filters, ...state.filters ?? []],
}), }),
function(body){ function(body){
// stage III post... // stage III post...
// NOTE: we are protecting the result from // NOTE: we are protecting the result from
@ -1200,12 +1168,9 @@ module.parser = {
if(!name){ if(!name){
return '' } return '' }
//* XXX LOCAL_STATE // XXX LOCAL_STATE
var vars = state.parent.vars ??= {} var vars = state.parent.vars ??= {}
//var vars = state.root.vars ??= {} //var vars = state.root.vars ??= {}
/*/
var vars = state.vars ??= {}
//*/
return Promise.awaitOrRun( return Promise.awaitOrRun(
this.execNested(page, name, state), this.execNested(page, name, state),
@ -1350,12 +1315,9 @@ module.parser = {
var that = this var that = this
var name = args.name var name = args.name
//* XXX LOCAL_STATE // XXX LOCAL_STATE
var slots = state.parent.slots ??= {} var slots = state.parent.slots ??= {}
//var slots = state.root.slots ??= {} //var slots = state.root.slots ??= {}
/*/
var slots = state.slots ??= {}
//*/
return Promise.awaitOrRun( return Promise.awaitOrRun(
this.execNested(page, name, state), this.execNested(page, name, state),
@ -1714,12 +1676,9 @@ module.parser = {
function(page, args, body, state){ function(page, args, body, state){
var that = this var that = this
//* XXX LOCAL_STATE // XXX LOCAL_STATE
var macros = state.parent.macros ??= {} var macros = state.parent.macros ??= {}
//var macros = state.root.macros ??= {} //var macros = state.root.macros ??= {}
/*/
var macros = state.macros ??= {}
//*/
return Promise.awaitOrRun( return Promise.awaitOrRun(
this.execNested(page, args.name, state), this.execNested(page, args.name, state),

View File

@ -399,7 +399,55 @@ test.Setups({
// XXX // XXX
// XXX filter... // XXX filter...
// XXX filter_local: function(assert){
return {
page: P,
code: [
'<filter upper>moo</filter>',
'MOO' ]} },
filter_local_sync: function(assert){
return {
page: P,
code: [
'<filter upper>@include(/page)</filter>',
'PAGE' ]} },
filter_local_async: function(assert){
return {
page: P,
code: [
'<filter upper>@include(/async/page)</filter>',
'PAGE' ]} },
filter_global: function(assert){
return {
page: P,
code: [
'<filter upper/>moo',
'MOO' ]} },
filter_global_sync: function(assert){
return {
page: P,
code: [
'<filter upper/>@include(/page)',
'PAGE' ]} },
filter_global_async: function(assert){
return {
page: P,
code: [
'<filter upper/>@include(/async/page)',
'PAGE' ]} },
filter_mixed_isolated_sync: function(assert){
return {
page: P,
code: [
'<filter upper/>local <filter -upper>@include(/page)</filter>',
'LOCAL Page' ]} },
// XXX BUG
filter_mixed_isolated_async: function(assert){
return {
page: P,
code: [
'<filter upper/>local <filter -upper>@include(/async/page)</filter>',
'LOCAL Page' ]} },
}) })