mirror of
https://github.com/flynx/pWiki.git
synced 2026-10-03 12:51:40 +00:00
Compare commits
No commits in common. "ab53f86ed0a6d2306c642bda61c9fba14d34d266" and "1411a2cf6d20c652307d17aab0e6982c6fb6ea74" have entirely different histories.
ab53f86ed0
...
1411a2cf6d
@ -647,19 +647,34 @@ module.BaseParser = {
|
|||||||
&& (body = this.expand(page, body, state, nested_handlers))
|
&& (body = this.expand(page, body, state, nested_handlers))
|
||||||
|
|
||||||
// call macro...
|
// call macro...
|
||||||
|
// XXX since this can be async and if so it will be mixed
|
||||||
|
// into the next .wait*, we'll need to explicitly pass
|
||||||
|
// and then thread the current .wait* promises before
|
||||||
|
// overwriting, to avoid wait-for-self deadlocks...
|
||||||
|
// ...the question is how to thread it...
|
||||||
|
// one way to do this is to split state into:
|
||||||
|
// state - current state of eval, mutable for all
|
||||||
|
// context - the context of evaluation of the curent
|
||||||
|
// macro, unique per macro, this would
|
||||||
|
// also be good to store things like
|
||||||
|
// line numbers and the like...
|
||||||
|
// ways to organize this:
|
||||||
|
// - context.state - nesting
|
||||||
|
// - state, context - sepatrate args
|
||||||
|
// - state.__proto__ - protorype
|
||||||
|
// ...technically need a way to call .exec(..) and wait
|
||||||
|
// for the correct promise from inside a macro...
|
||||||
//* XXX LOCAL_STATE
|
//* XXX LOCAL_STATE
|
||||||
// NOTE: here we separate local macro state and global/parent
|
// XXX think this is the best way to go, but needs the rest
|
||||||
// state via the prototpype...
|
// of the code refactored + still need to experiment...
|
||||||
// This is mainly needed to sparate promises, since the
|
// XXX part of the problem is that this mechanism is not used
|
||||||
// inicial execution is done on order of occurenca while
|
// later (.resolve(..) and .finalize(..)) which creates
|
||||||
// each macro can wait async for an arbitrary amount of
|
// the same sync problems there too -- need to unify
|
||||||
// time it only should care about what was promised
|
// both mechanisms...
|
||||||
// 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 state...
|
||||||
__proto__: state,
|
__proto__: state,
|
||||||
root: state.root ?? state,
|
state,
|
||||||
parent: state,
|
|
||||||
// local state...
|
// local state...
|
||||||
waitAll: state.waitAll,
|
waitAll: state.waitAll,
|
||||||
waitNested: state.waitNested,
|
waitNested: state.waitNested,
|
||||||
@ -692,13 +707,9 @@ module.BaseParser = {
|
|||||||
res.then(
|
res.then(
|
||||||
function(value){
|
function(value){
|
||||||
if(state.waitAll === all){
|
if(state.waitAll === all){
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
delete state.waitAll }
|
||||||
state.waitAll = undefined }
|
|
||||||
//delete state.waitAll }
|
|
||||||
if(state.waitNested === nested){
|
if(state.waitNested === nested){
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
delete state.waitNested }
|
||||||
state.waitNested = undefined }
|
|
||||||
//delete state.waitNested }
|
|
||||||
delete elem.resolving
|
delete elem.resolving
|
||||||
elem.value = value
|
elem.value = value
|
||||||
// XXX should we resolve to value or elem???
|
// XXX should we resolve to value or elem???
|
||||||
@ -723,15 +734,11 @@ module.BaseParser = {
|
|||||||
.then(function(){
|
.then(function(){
|
||||||
// only cleanup our own mess =)
|
// only cleanup our own mess =)
|
||||||
waitAll === state.waitAll
|
waitAll === state.waitAll
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
&& (delete state.waitAll) })
|
||||||
&& (state.waitAll = undefined) })
|
|
||||||
//&& (delete state.waitAll) })
|
|
||||||
&& (wait = state.wait = waitAll
|
&& (wait = state.wait = waitAll
|
||||||
.then(function(){
|
.then(function(){
|
||||||
wait === state.wait
|
wait === state.wait
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
&& (delete state.wait)
|
||||||
&& (state.wait = null)
|
|
||||||
//&& (delete state.wait)
|
|
||||||
return elems }))
|
return elems }))
|
||||||
var waitNested = state.waitNested
|
var waitNested = state.waitNested
|
||||||
state.waitNested
|
state.waitNested
|
||||||
@ -739,9 +746,7 @@ module.BaseParser = {
|
|||||||
.then(function(){
|
.then(function(){
|
||||||
// only cleanup our own mess =)
|
// only cleanup our own mess =)
|
||||||
waitNested === state.waitNested
|
waitNested === state.waitNested
|
||||||
// XXX LOCAL_STATE_CLEANUP
|
&& (delete state.waitNested) })
|
||||||
&& (state.waitNested = undefined) })
|
|
||||||
//&& (delete state.waitNested) })
|
|
||||||
|
|
||||||
return elems },
|
return elems },
|
||||||
|
|
||||||
@ -762,29 +767,6 @@ module.BaseParser = {
|
|||||||
// XXX can we prevent reaces over state.unresolved???
|
// XXX can we prevent reaces over state.unresolved???
|
||||||
// it can be deleted when calling .exec(..) / .execNested(..)
|
// it can be deleted when calling .exec(..) / .execNested(..)
|
||||||
// while parsing, for example from within a macro...
|
// while parsing, for example from within a macro...
|
||||||
// XXX this somehow blocks the execution of .expand(..)
|
|
||||||
// This fullly runs:
|
|
||||||
// .expand(.., '@echo(A)@source(/async/echo)@echo(B)@include(/async/echo)@echo(C)', ..)
|
|
||||||
// printing:
|
|
||||||
// ---- A
|
|
||||||
// -- A
|
|
||||||
// ---- B
|
|
||||||
// ---- C
|
|
||||||
// ---- Page
|
|
||||||
// -- Page
|
|
||||||
// ---- Page
|
|
||||||
// -- B
|
|
||||||
// -- Page
|
|
||||||
// -- C
|
|
||||||
// This blocks:
|
|
||||||
// .resolve(.., '@echo(A)@source(/async/echo)@echo(B)@include(/async/echo)@echo(C)', ..)
|
|
||||||
// printing:
|
|
||||||
// ---- A
|
|
||||||
// -- A
|
|
||||||
// ---- B
|
|
||||||
// ---- C
|
|
||||||
// ...looks like we are still getting a deadlock...
|
|
||||||
// -> the issue seems to be in a nested call to .execNested(..) -> .finalize(..)
|
|
||||||
resolve: function(page, ast, state={}, nested_handlers={}){
|
resolve: function(page, ast, state={}, nested_handlers={}){
|
||||||
var that = this
|
var that = this
|
||||||
ast = typeof(ast) != 'object' ?
|
ast = typeof(ast) != 'object' ?
|
||||||
@ -795,7 +777,6 @@ module.BaseParser = {
|
|||||||
|
|
||||||
// XXX LOCAL_STATE
|
// XXX LOCAL_STATE
|
||||||
//state.unresolved = []
|
//state.unresolved = []
|
||||||
var unresolved = []
|
|
||||||
|
|
||||||
// merge resolved elements into the last item of elems...
|
// merge resolved elements into the last item of elems...
|
||||||
var elems = []
|
var elems = []
|
||||||
@ -809,11 +790,6 @@ module.BaseParser = {
|
|||||||
Promise.awaitOrRun(
|
Promise.awaitOrRun(
|
||||||
// if not everything is resolved, delay the stage II
|
// if not everything is resolved, delay the stage II
|
||||||
// callbacks till .wait is done...
|
// callbacks till .wait is done...
|
||||||
// NOTE: this depends on that JS is single thread
|
|
||||||
// and we can't have state.wait resolve in
|
|
||||||
// the middle of this loop.
|
|
||||||
// NOTE: waiting promises resolving is also done in
|
|
||||||
// FIFO orderm thus maintaining order of execution
|
|
||||||
state.wait,
|
state.wait,
|
||||||
function(){
|
function(){
|
||||||
return elem = e.value =
|
return elem = e.value =
|
||||||
@ -838,10 +814,7 @@ 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...
|
state.unresolved
|
||||||
// ...use the same mechanism here as in .expand(..)
|
|
||||||
//state.unresolved
|
|
||||||
unresolved
|
|
||||||
.push(elem.resolving instanceof Promise ?
|
.push(elem.resolving instanceof Promise ?
|
||||||
elem.resolving
|
elem.resolving
|
||||||
: elem)
|
: elem)
|
||||||
@ -850,14 +823,6 @@ module.BaseParser = {
|
|||||||
// are the responsibility of the respective macros...
|
// are the responsibility of the respective macros...
|
||||||
elems.push(elem) }
|
elems.push(elem) }
|
||||||
|
|
||||||
var resolving =
|
|
||||||
state.wait =
|
|
||||||
Promise.all([state.wait, ...unresolved])
|
|
||||||
// cleanup...
|
|
||||||
.then(function(){
|
|
||||||
if(state.wait === resolving){
|
|
||||||
delete state.wait } })
|
|
||||||
|
|
||||||
return elems },
|
return elems },
|
||||||
|
|
||||||
isResolved: function(ast){
|
isResolved: function(ast){
|
||||||
@ -873,7 +838,6 @@ module.BaseParser = {
|
|||||||
// Merge and apply global filters (stage III)...
|
// Merge and apply global filters (stage III)...
|
||||||
//
|
//
|
||||||
// - ensure the ast is fully resolved
|
// - ensure the ast is fully resolved
|
||||||
// resolve and re-resolve untill all done
|
|
||||||
// - apply stage III pre handlers
|
// - apply stage III pre handlers
|
||||||
// - apply global filters
|
// - apply global filters
|
||||||
// - apply stage III post handlers
|
// - apply stage III post handlers
|
||||||
@ -894,36 +858,25 @@ module.BaseParser = {
|
|||||||
.flat() }
|
.flat() }
|
||||||
var resolve = function(ast){
|
var resolve = function(ast){
|
||||||
return Promise.awaitOrRun(
|
return Promise.awaitOrRun(
|
||||||
// XXX LOCAL_STATE
|
...(state.unresolved ?? []),
|
||||||
//...(state.unresolved ?? []),
|
|
||||||
state.hasOwnProperty('wait') ?
|
|
||||||
state.wait
|
|
||||||
// XXX
|
|
||||||
: null,
|
|
||||||
function(){
|
function(){
|
||||||
//delete state.unresolved
|
delete state.unresolved
|
||||||
// re-resolve...
|
// re-resolve...
|
||||||
ast = that.resolve(page, ast, state, nested_handlers)
|
ast = that.resolve(page, ast, state, nested_handlers)
|
||||||
|
|
||||||
// NOTE: this is essentially running in the same frame
|
// NOTE: this is essentially running in the same frame
|
||||||
// as .resolve(..) above so there should not be
|
// as .resolve(..) above so there should not be
|
||||||
// any races to delete .unresolved...
|
// any races to delete .unresolved...
|
||||||
//return state.unresolved ?
|
return state.unresolved ?
|
||||||
//return state.hasOwnProperty('wait') ?
|
|
||||||
return !that.isResolved(ast) ?
|
|
||||||
resolve(ast)
|
resolve(ast)
|
||||||
: ast }) }
|
: ast }) }
|
||||||
|
|
||||||
ast = this.resolve(page, ast, state, nested_handlers)
|
ast = this.resolve(page, ast, state, nested_handlers)
|
||||||
|
|
||||||
return Promise.awaitOrRun(
|
return Promise.awaitOrRun(
|
||||||
// XXX LOCAL_STATE
|
|
||||||
// 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) ?
|
|
||||||
state[wait]
|
|
||||||
: null,
|
|
||||||
function(){
|
function(){
|
||||||
// NOTE: in an async world where any promised macro can
|
// NOTE: in an async world where any promised macro can
|
||||||
// call .exec(..) / .execNested(..) we can't trust
|
// call .exec(..) / .execNested(..) we can't trust
|
||||||
@ -931,10 +884,8 @@ 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
|
(state.unresolved
|
||||||
// || !that.isResolved(ast)) ?
|
|| !that.isResolved(ast)) ?
|
||||||
//state.hasOwnProperty('wait') ?
|
|
||||||
!that.isResolved(ast) ?
|
|
||||||
resolve(ast)
|
resolve(ast)
|
||||||
: ast,
|
: ast,
|
||||||
function(ast){
|
function(ast){
|
||||||
@ -956,7 +907,6 @@ module.BaseParser = {
|
|||||||
|
|
||||||
// XXX
|
// 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...
|
/* 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, 'unresolved') },
|
||||||
return this.exec(page, ast, state, nested_handlers, 'waitNested') },
|
return this.exec(page, ast, state, nested_handlers, 'waitNested') },
|
||||||
@ -1048,7 +998,7 @@ module.parser = {
|
|||||||
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...
|
// XXX this works and sequences correctly...
|
||||||
state.waitNested,
|
//state.waitNested,
|
||||||
// XXX this deadlocks...
|
// XXX this deadlocks...
|
||||||
// calling .execNested(..) from any macro (@include(..)
|
// calling .execNested(..) from any macro (@include(..)
|
||||||
// in the example code) will deadlock the execution
|
// in the example code) will deadlock the execution
|
||||||
@ -1058,7 +1008,7 @@ module.parser = {
|
|||||||
// - run:
|
// - run:
|
||||||
// @echo(A)@source(/async/echo)@echo(B)@include(/async/echo)@echo(C)
|
// @echo(A)@source(/async/echo)@echo(B)@include(/async/echo)@echo(C)
|
||||||
// -> need a way to call .exex(..) while evaluating...
|
// -> need a way to call .exex(..) while evaluating...
|
||||||
//this.execNested(page, '', state),
|
this.execNested(page, '', state),
|
||||||
// XXX this also does not work...
|
// XXX this also does not work...
|
||||||
//this.resolve(page, '', state),
|
//this.resolve(page, '', state),
|
||||||
function(){
|
function(){
|
||||||
@ -1200,9 +1150,8 @@ module.parser = {
|
|||||||
if(!name){
|
if(!name){
|
||||||
return '' }
|
return '' }
|
||||||
|
|
||||||
//* XXX LOCAL_STATE
|
/* XXX LOCAL_STATE
|
||||||
var vars = state.parent.vars ??= {}
|
var vars = state.state.vars ??= {}
|
||||||
//var vars = state.root.vars ??= {}
|
|
||||||
/*/
|
/*/
|
||||||
var vars = state.vars ??= {}
|
var vars = state.vars ??= {}
|
||||||
//*/
|
//*/
|
||||||
@ -1350,9 +1299,8 @@ 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.state.slots ??= {}
|
||||||
//var slots = state.root.slots ??= {}
|
|
||||||
/*/
|
/*/
|
||||||
var slots = state.slots ??= {}
|
var slots = state.slots ??= {}
|
||||||
//*/
|
//*/
|
||||||
@ -1714,9 +1662,8 @@ 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.state.macros ??= {}
|
||||||
//var macros = state.root.macros ??= {}
|
|
||||||
/*/
|
/*/
|
||||||
var macros = state.macros ??= {}
|
var macros = state.macros ??= {}
|
||||||
//*/
|
//*/
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user