more of the render flow converted to semi-async...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2023-02-11 23:12:51 +03:00
parent 70803d9f07
commit 7a1956b760

View File

@ -267,6 +267,20 @@ object.Constructor('BasePage', {
return this.store.delete(pwpath.relative(this.path, path)) }, return this.store.delete(pwpath.relative(this.path, path)) },
__energetic: undefined, __energetic: undefined,
//* XXX EXPERIMENTAL
get energetic(){
return this.__energetic === true
|| ((this.actions
&& this.actions[this.name]
&& !!this[
this.actions[this.name] === true ?
this.name
: this.actions[this.name] ].energetic)
|| Promise.awaitOrRun(
this.store.isEnergetic(this.path),
function(res){
return !!res })) },
/*/ // XXX ASYNC
get energetic(){ return async function(){ get energetic(){ return async function(){
return this.__energetic === true return this.__energetic === true
|| ((this.actions || ((this.actions
@ -276,12 +290,68 @@ object.Constructor('BasePage', {
this.name this.name
: this.actions[this.name] ].energetic) : this.actions[this.name] ].energetic)
|| !!await this.store.isEnergetic(this.path)) }.call(this) }, || !!await this.store.isEnergetic(this.path)) }.call(this) },
//*/
set energetic(value){ set energetic(value){
this.__energetic = value }, this.__energetic = value },
// page data... // page data...
// //
strict: undefined, strict: undefined,
//* XXX EXPERIMENTAL
get data(){
var that = this
// direct actions...
if(this.actions
&& this.actions[this.name]){
var name =
this.actions[this.name] === true ?
this.name
: this.actions[this.name]
var args = this.args
var page = this.get('..', {args})
return Promise.awaitOrRun(
(this.isPattern
&& !this.__energetic
&& !page[name].energetic) ?
page
.map(function(page){
var res = page[name]
return typeof(res) == 'function' ?
res.bind(page.get(name, {args}))
: function(){
return res } })
: page[name],
function(res){
return typeof(res) == 'function' ?
res.bind(that)
: res instanceof Array ?
res
: function(){
return res } },
// NOTE: we are passing null into the error handler to
// prevent the actual data (function) from being
// consumed...
null) }
// store data...
return Promise.awaitOrRun(
this.energetic,
function(energetic){
// pattern...
// NOTE: we need to make sure each page gets the chance to handle
// its context (i.e. bind action to page)....
if(that.isPattern
&& !energetic){
return that
.map(function(page){
return page.data }) }
// single page...
return Promise.awaitOrRun(
that.store.get(that.path, !!that.strict, !!energetic),
function(res){
return typeof(res) == 'function' ?
res.bind(that)
: res }) }) },
/*/ // XXX ASYNC
get data(){ return (async function(){ get data(){ return (async function(){
// direct actions... // direct actions...
if(this.actions if(this.actions
@ -325,6 +395,7 @@ object.Constructor('BasePage', {
return typeof(res) == 'function' ? return typeof(res) == 'function' ?
res.bind(this) res.bind(this)
: res }).call(this) }, : res }).call(this) },
//*/
set data(value){ set data(value){
if(this.actions if(this.actions
&& this.actions[this.name]){ && this.actions[this.name]){
@ -399,6 +470,7 @@ object.Constructor('BasePage', {
// set... // set...
this.__update__(value) }, this.__update__(value) },
// XXX ASYNC???
get type(){ return async function(){ get type(){ return async function(){
return this.store.isStore(this.path) ? return this.store.isStore(this.path) ?
'store' 'store'
@ -1332,8 +1404,7 @@ object.Constructor('Page', BasePage, {
['shown', 'hidden', ['shown', 'hidden',
'parent', 'parent',
'inc', 'dec', 'inc', 'dec',
'alpha', 'Alpha', 'alpha', 'Alpha', 'roman', 'Roman']],
'roman', 'Roman']],
/*/ /*/
['shown', 'hidden']], ['shown', 'hidden']],
//*/ //*/
@ -1714,9 +1785,11 @@ object.Constructor('Page', BasePage, {
// XXX this is html/web specific, should it be here??? // XXX this is html/web specific, should it be here???
// ... // ...
// XXX should this be .raw or .parse()??? // XXX should this be .raw or .parse()???
// XXX ASYNC???
quote: async function(energetic=false){ quote: async function(energetic=false){
return this.get('..:$ARGS', {energetic: await this.energetic}).raw//parse() return Promise.awaitOrRun(
.then(function(res){ this.get('..:$ARGS', {energetic: await this.energetic}).raw,
function(res){
return res instanceof Array ? return res instanceof Array ?
res.map(pwpath.quoteHTML) res.map(pwpath.quoteHTML)
: pwpath.quoteHTML(res) }) }, : pwpath.quoteHTML(res) }) },
@ -1798,6 +1871,45 @@ object.Constructor('Page', BasePage, {
// NOTE: when matching multiple pages this will return a list... // NOTE: when matching multiple pages this will return a list...
// //
// XXX revise how we handle .strict mode... // XXX revise how we handle .strict mode...
// XXX EXPERIMENTAL
get raw(){
var that = this
return Promise.awaitOrRun(
this.data,
function(data){
// no data...
// NOTE: if we hit this it means that nothing was resolved,
// not even the System/NotFound page, i.e. something
// went really wrong...
// NOTE: in .strict mode this will explicitly fail and not try
// to recover...
if(data == null){
if(!this.strict
&& this.NOT_FOUND_ERROR){
var msg = this.get(this.NOT_FOUND_ERROR)
return Promise.awaitOrRun(
msg.match(),
function(msg){
return msg.raw }) }
// last resort...
throw new Error('NOT FOUND ERROR: '+ this.path) }
// get the data...
return (
// action...
typeof(data) == 'function' ?
data()
// multiple matches...
: data instanceof Array ?
// XXX
Promise.all(data
.map(function(d){
return typeof(d) == 'function'?
d()
: d.text })
.flat())
: data.text ) },
null) },
/*/ // XXX ASYNC
get raw(){ return (async function(){ get raw(){ return (async function(){
var data = await this.data var data = await this.data
// no data... // no data...
@ -1828,6 +1940,7 @@ object.Constructor('Page', BasePage, {
: d.text }) : d.text })
.flat()) .flat())
: data.text )}).call(this) }, : data.text )}).call(this) },
//*/
set raw(value){ set raw(value){
this.data = {text: value} }, this.data = {text: value} },
//this.onTextUpdate(value) }, //this.onTextUpdate(value) },
@ -1896,7 +2009,45 @@ object.Constructor('Page', BasePage, {
// or render as any other page??? // or render as any other page???
// ...currently they are rendered in the context of the page and // ...currently they are rendered in the context of the page and
// not in their own context... // not in their own context...
// XXX revise how we handle strict mode... /*/ XXX revise how we handle strict mode...
get text(){
// strict mode -- break on non-existing pages...
if(this.strict
// XXX
&& !await this.resolve(true)){
throw new Error('NOT FOUND ERROR: '+ this.location) }
var path = pwpath.split(this.path)
;(path.at(-1) ?? '')[0] == '_'
|| path.push(this.PAGE_TEMPLATE)
var tpl = pwpath.join(path)
var tpl_name = path.pop()
//var tpl_name = path.at(-1)
// get the template relative to the top most pattern...
return Promise.awaitOrRun(
this.get(tpl).find(true),
function(tpl){
if(!tpl){
console.warn('UNKNOWN RENDER TEMPLATE: '+ tpl_name)
return this.get(this.NOT_FOUND_TEMPLATE_ERROR).parse() }
var depends = this.depends = new Set([tpl])
// do the parse...
// NOTE: we render the template in context of page...
return that
// NOTE: this.path can both contain a template and not, this
// normalizes it to the path up to the template path...
.get(path, {args: this.args})
.parse(
this.get(
'/'+tpl,
{args: this.args}).raw,
{
depends,
renderer: this,
}) }.bind(this)) },
/*/ // XXX ASYNC
get text(){ return (async function(){ get text(){ return (async function(){
// strict mode -- break on non-existing pages... // strict mode -- break on non-existing pages...
if(this.strict if(this.strict
@ -1931,6 +2082,7 @@ object.Constructor('Page', BasePage, {
depends, depends,
renderer: this, renderer: this,
}) }).call(this) }, }) }).call(this) },
//*/
set text(value){ set text(value){
this.data = {text: value} }, this.data = {text: value} },
//this.onTextUpdate(value) }, //this.onTextUpdate(value) },
@ -2238,14 +2390,14 @@ module.System = {
<slot header> <slot header>
<a href="#/list">&#9776</a> <a href="#/list">&#9776</a>
<!--
<a href="javascript:history.back()">&#5130;</a> <a href="javascript:history.back()">&#5130;</a>
<a href="javascript:history.foreward()">&#5125;</a> <a href="javascript:history.foreward()">&#5125;</a>
<a href="#<slot parent>../:@arg(all)</slot>">&#5123;</a> <a href="#<slot parent>../:@arg(all)</slot>">&#5123;</a>
<!-- -->
<a href="javascript:history.back()">&#129120;</a> <a href="javascript:history.back()">&#129120;</a>
<a href="javascript:history.foreward()">&#129122;</a> <a href="javascript:history.foreward()">&#129122;</a>
<a href="#<slot parent>../:@arg(all)</slot>">&#129121;</a> <a href="#<slot parent>../:@arg(all)</slot>">&#129121;</a>
-->
<!-- use css for spacing... --> <!-- use css for spacing... -->
&nbsp;&nbsp; &nbsp;&nbsp;
<!-- XXX make this editable + inherit args... --> <!-- XXX make this editable + inherit args... -->
@ -2410,9 +2562,14 @@ module.System = {
text: object.doc` text: object.doc`
<slot header> <slot header>
<a href="#/list">&#9776</a> <a href="#/list">&#9776</a>
<a href="javascript:history.back()">&#129120;</a>
<a href="javascript:history.foreward()">&#129122;</a>
<a href="#<slot parent>../:@arg(all)</slot>">&#129121;</a>
<!--
<a href="javascript:history.back()">&#5130;</a> <a href="javascript:history.back()">&#5130;</a>
<a href="javascript:history.foreward()">&#5125;</a> <a href="javascript:history.foreward()">&#5125;</a>
<a href="#@source(s ../../path)/list">&#5123;</a> <a href="#@source(s ../../path)/list">&#5123;</a>
-->
&nbsp;&nbsp; &nbsp;&nbsp;
@source(../path) @source(../path)
</slot> </slot>