Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[experiment]: Demo app for glimmer-next renderer #20711

Draft
wants to merge 23 commits into
base: main
Choose a base branch
from
Draft
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import type { Reference } from '@glimmer/reference';
import { childRefFor, createComputeRef, createPrimitiveRef, valueForRef } from '@glimmer/reference';
import { reifyPositional } from '@glimmer/runtime';
import { EMPTY_ARRAY, unwrapTemplate } from '@glimmer/util';
import { unwrapTemplate } from '@glimmer/utils';

Check failure on line 31 in packages/@ember/-internals/glimmer/lib/component-managers/curly.ts

View workflow job for this annotation

GitHub Actions / Linting

Unable to resolve path to module '@glimmer/utils'

Check failure on line 31 in packages/@ember/-internals/glimmer/lib/component-managers/curly.ts

View workflow job for this annotation

GitHub Actions / Type Checking (current version)

Cannot find module '@glimmer/utils' or its corresponding type declarations.
import {
beginTrackFrame,
beginUntrackFrame,
Expand All @@ -54,6 +54,7 @@

export const ARGS = enumerableSymbol('ARGS');
export const HAS_BLOCK = enumerableSymbol('HAS_BLOCK');
const EMPTY_ARRAY = [];

Check failure on line 57 in packages/@ember/-internals/glimmer/lib/component-managers/curly.ts

View workflow job for this annotation

GitHub Actions / Linting

Delete `·`

Check failure on line 57 in packages/@ember/-internals/glimmer/lib/component-managers/curly.ts

View workflow job for this annotation

GitHub Actions / Type Checking (current version)

Variable 'EMPTY_ARRAY' implicitly has type 'any[]' in some locations where its type cannot be determined.

export const DIRTY_TAG = Symbol('DIRTY_TAG');
export const IS_DISPATCHING_ATTRS = Symbol('IS_DISPATCHING_ATTRS');
Expand Down Expand Up @@ -232,7 +233,7 @@
return null;
}

return { positional: EMPTY_ARRAY as readonly Reference[], named };

Check failure on line 236 in packages/@ember/-internals/glimmer/lib/component-managers/curly.ts

View workflow job for this annotation

GitHub Actions / Type Checking (current version)

Variable 'EMPTY_ARRAY' implicitly has an 'any[]' type.
}

/*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import { capabilityFlagsFrom } from '@glimmer/manager';
import type { Reference } from '@glimmer/reference';
import { createConstRef, valueForRef } from '@glimmer/reference';
import { unwrapTemplate } from '@glimmer/util';
import { unwrapTemplate } from '@glimmer/utils';

Check failure on line 24 in packages/@ember/-internals/glimmer/lib/component-managers/mount.ts

View workflow job for this annotation

GitHub Actions / Linting

Unable to resolve path to module '@glimmer/utils'

Check failure on line 24 in packages/@ember/-internals/glimmer/lib/component-managers/mount.ts

View workflow job for this annotation

GitHub Actions / Type Checking (current version)

Cannot find module '@glimmer/utils' or its corresponding type declarations.
import type RuntimeResolver from '../resolver';

interface EngineState {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
import type { Reference } from '@glimmer/reference';
import { createConstRef, valueForRef } from '@glimmer/reference';
import { EMPTY_ARGS } from '@glimmer/runtime';
import { unwrapTemplate } from '@glimmer/util';
import { unwrapTemplate } from '@glimmer/utils';

Check failure on line 24 in packages/@ember/-internals/glimmer/lib/component-managers/outlet.ts

View workflow job for this annotation

GitHub Actions / Linting

Unable to resolve path to module '@glimmer/utils'

Check failure on line 24 in packages/@ember/-internals/glimmer/lib/component-managers/outlet.ts

View workflow job for this annotation

GitHub Actions / Type Checking (current version)

Cannot find module '@glimmer/utils' or its corresponding type declarations.

import type { DynamicScope } from '../renderer';
import type { OutletState } from '../utils/outlet';
Expand Down
10 changes: 9 additions & 1 deletion packages/@ember/-internals/glimmer/lib/components/internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,17 @@
} from '@glimmer/interfaces';
import { setComponentTemplate, setInternalComponentManager } from '@glimmer/manager';
import type { Reference } from '@glimmer/reference';
import { createConstRef, isConstRef, valueForRef } from '@glimmer/reference';
import { reference } from '@lifeart/gxt/glimmer-compatibility';

Check failure on line 18 in packages/@ember/-internals/glimmer/lib/components/internal.ts

View workflow job for this annotation

GitHub Actions / Linting

Unable to resolve path to module '@lifeart/gxt/glimmer-compatibility'

Check failure on line 18 in packages/@ember/-internals/glimmer/lib/components/internal.ts

View workflow job for this annotation

GitHub Actions / Type Checking (current version)

Cannot find module '@lifeart/gxt/glimmer-compatibility' or its corresponding type declarations.
// import { createConstRef, isConstRef, valueForRef } from '@glimmer/reference';
import { untrack } from '@glimmer/validator';

const { createConstRef } = reference;
function isConstRef() {
return true;
}
function valueForRef(ref) {
return ref;
}
function NOOP(): void {}

export type EventListener = (event: Event) => void;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import type { InternalOwner } from '@ember/-internals/owner';
import type { Helper, HelperDefinitionState } from '@glimmer/interfaces';
import { setInternalHelperManager } from '@glimmer/manager';
// import { setInternalHelperManager } from '@glimmer/manager';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why comment this out?

If we need to re-define the implementation, I think that could happen in this PR (like, if it's copying from glimmer-next, for example)


export function internalHelper(helper: Helper<InternalOwner>): HelperDefinitionState {
return setInternalHelperManager(helper, {});
return function () {
console.log('internal helper', this, [...arguments]);

Check failure on line 7 in packages/@ember/-internals/glimmer/lib/helpers/internal-helper.ts

View workflow job for this annotation

GitHub Actions / Linting

Unexpected console statement
return helper(...arguments);
}

Check failure on line 9 in packages/@ember/-internals/glimmer/lib/helpers/internal-helper.ts

View workflow job for this annotation

GitHub Actions / Linting

Insert `;`
}
60 changes: 38 additions & 22 deletions packages/@ember/-internals/glimmer/lib/renderer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import { getOwner } from '@ember/-internals/owner';
import { guidFor } from '@ember/-internals/utils';
import { getViewElement, getViewId } from '@ember/-internals/views';
import { renderComponent, runDestructors } from '@lifeart/gxt';
import { assert } from '@ember/debug';
import { _backburner, _getCurrentRunLoop } from '@ember/runloop';
import { destroy } from '@glimmer/destroyable';
Expand Down Expand Up @@ -31,14 +32,14 @@
import type { CurriedValue } from '@glimmer/runtime';
import {
clientBuilder,
curry,
// curry,
DOMChanges,
DOMTreeConstruction,
inTransaction,
renderMain,

Check failure on line 39 in packages/@ember/-internals/glimmer/lib/renderer.ts

View workflow job for this annotation

GitHub Actions / Linting

'renderMain' is defined but never used. Allowed unused vars must match /^_/u
runtimeContext,
} from '@glimmer/runtime';
import { unwrapTemplate } from '@glimmer/util';
import { unwrapTemplate } from '@glimmer/utils';

Check failure on line 42 in packages/@ember/-internals/glimmer/lib/renderer.ts

View workflow job for this annotation

GitHub Actions / Linting

Unable to resolve path to module '@glimmer/utils'
import { CURRENT_TAG, validateTag, valueForTag } from '@glimmer/validator';
import type { SimpleDocument, SimpleElement, SimpleNode } from '@simple-dom/interface';
import RSVP from 'rsvp';
Expand All @@ -64,6 +65,23 @@
[BOUNDS]: Bounds | null;
}

function curry(
type: T,
spec: object | string | any,
owner: any,
args: any | null,
resolved = false
) {
console.log('curry');

Check failure on line 75 in packages/@ember/-internals/glimmer/lib/renderer.ts

View workflow job for this annotation

GitHub Actions / Linting

Unexpected console statement
return {
type,
spec,
owner,
args,
resolved,
};
}

export class DynamicScope implements GlimmerDynamicScope {
constructor(public view: View | null, public outletState: Reference<OutletState | undefined>) {}

Expand Down Expand Up @@ -129,13 +147,13 @@
constructor(
public root: Component | OutletView,
public runtime: RuntimeContext,
context: CompileTimeCompilationContext,
_context: CompileTimeCompilationContext,
owner: InternalOwner,
template: Template,
self: Reference<unknown>,
parentElement: SimpleElement,
dynamicScope: DynamicScope,
builder: IBuilder
_dynamicScope: DynamicScope,
_builder: IBuilder
) {
assert(
`You cannot render \`${valueForRef(self)}\` without a template.`,
Expand All @@ -146,23 +164,16 @@
this.result = undefined;
this.destroyed = false;

this.render = errorLoopTransaction(() => {
let layout = unwrapTemplate(template).asLayout();

let iterator = renderMain(
runtime,
context,
owner,
self,
builder(runtime.env, { element: parentElement, nextSibling: null }),
layout,
dynamicScope
);

let result = (this.result = iterator.sync());
// console.log(layout);

// override .render function after initial render
this.render = errorLoopTransaction(() => result.rerender({ alwaysRevalidate: false }));
this.render = errorLoopTransaction(() => {
let layout = unwrapTemplate(template).asLayout().compile();
const layoutInstance = new layout(this);
// @ts-expect-error fine
this.result = renderComponent(layoutInstance, parentElement, owner);
this.render = errorLoopTransaction(() => {
// fine
});
});
}

Expand Down Expand Up @@ -195,7 +206,11 @@

*/

inTransaction(env, () => destroy(result!));
inTransaction(env, () => {
// @ts-expect-error foo-bar
runDestructors(result.ctx);
destroy(result!);
});
}
}
}
Expand Down Expand Up @@ -370,6 +385,7 @@
// renderer HOOKS

appendOutletView(view: OutletView, target: SimpleElement): void {
console.log('appendOutletView', view, target);
let definition = createRootOutlet(view);
this._appendDefinition(
view,
Expand Down
9 changes: 4 additions & 5 deletions packages/@ember/-internals/glimmer/lib/templates/empty.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate('', {
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/empty.hbs',
strictMode: true,
});
import { hbs } from '@lifeart/gxt';
export default function emptyTemplate() {
return hbs``;
};
18 changes: 5 additions & 13 deletions packages/@ember/-internals/glimmer/lib/templates/input.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
import { precompileTemplate } from '@ember/template-compilation';
import { on } from '@ember/modifier';
export default precompileTemplate(
`<input
import { hbs } from '@lifeart/gxt';
export default function InputTemplate() {
hbs`<input
{{!-- for compatibility --}}
id={{this.id}}
class={{this.class}}
Expand All @@ -17,12 +16,5 @@ export default precompileTemplate(
{{on "keyup" this.keyUp}}
{{on "paste" this.valueDidChange}}
{{on "cut" this.valueDidChange}}
/>`,
{
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/input.hbs',
strictMode: true,
scope() {
return { on };
},
}
);
/>`;
}
41 changes: 16 additions & 25 deletions packages/@ember/-internals/glimmer/lib/templates/link-to.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,21 @@
import { precompileTemplate } from '@ember/template-compilation';
import { on } from '@ember/modifier';
import { hbs } from '@lifeart/gxt';

export default precompileTemplate(
`<a
{{!-- for compatibility --}}
id={{this.id}}
class={{this.class}}
export default function LinkToTemplate() {
return hbs`<a
{{!-- for compatibility --}}
id={{this.id}}
class={{this.class}}

{{!-- deprecated attribute bindings --}}
role={{this.role}}
title={{this.title}}
rel={{this.rel}}
tabindex={{this.tabindex}}
target={{this.target}}
{{!-- deprecated attribute bindings --}}
role={{this.role}}
title={{this.title}}
rel={{this.rel}}
tabindex={{this.tabindex}}
target={{this.target}}

...attributes
...attributes

href={{this.href}}
href={{this.href}}

{{on 'click' this.click}}
>{{yield}}</a>`,
{
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/link-to.hbs',
strictMode: true,
scope() {
return { on };
},
}
);
{{on 'click' this.click}} >{{yield}}</a>`;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
import { Component } from '@lifeart/gxt';
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not @glimmer/component (not the real glimmer component, but re-defined in this PR, using glimmer-next apis?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

need to do some copy-paste from non-released branch - lifeart/glimmer-next#25


interface State {
outlets: {
main: State | undefined,
},
render: {
template(): () => unknown,
controller: unknown,
name: string,
}
}

export default class OutletHelper extends Component {
get state() {
return this.args.state().outlets.main || this.args.state();
}
get nextState() {
return () => {
return this.hasNext;
}
}
get hasNext() {
return this.state.outlets.main;
}
get canRender() {
return !!this?.state?.render;
}
get MyComponent() {

const state = this.state;
const render = state.render;
const tpl = render.template();
const args = {
get model() {
return render.model;
}
}
if (tpl.instance) {
return tpl.instance.template;
}
render.controller['args'] = args;
const tplComponentInstance = new tpl(args);
tplComponentInstance.template = tplComponentInstance.template.bind(render.controller);
// we need to provide stable refs here to avoid re-renders
tpl.instance = tplComponentInstance;
return tplComponentInstance.template;
}
get model() {
const state = this.state;
const render = state.render;
return render.model;
}
<template>
{{#if this.canRender}}
<this.MyComponent @model={{this.model}}>
{{#if this.hasNext}}
<OutletHelper @state={{this.nextState}} @root={{false}} />
{{/if}}
</this.MyComponent>

{{/if}}
</template>
}
20 changes: 13 additions & 7 deletions packages/@ember/-internals/glimmer/lib/templates/outlet.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,16 @@
import { precompileTemplate } from '@ember/template-compilation';
import { hbs } from '@lifeart/gxt';
import { outletHelper } from '../syntax/outlet';
import Outlet from './outlet-helper-component';

export default precompileTemplate(`{{component (outletHelper)}}`, {
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/outlet.hbs',
strictMode: true,
scope() {
return { outletHelper };
},
});

export default (owner) => {
console.log('outlet factory', owner);
globalThis.owner = owner;
return function(args) {
console.log('outlet', this, owner, ...arguments);
return hbs`{{#let (component Outlet state=(args.state)) as |Outlet|}}
<div>[main outlet template]<Outlet /></div>
{{/let}}`;
}
}
27 changes: 22 additions & 5 deletions packages/@ember/-internals/glimmer/lib/templates/root.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,22 @@
import { precompileTemplate } from '@ember/template-compilation';
export default precompileTemplate(`{{component this}}`, {
moduleName: 'packages/@ember/-internals/glimmer/lib/templates/root.hbs',
strictMode: true,
});
import { hbs, $_fin } from '@lifeart/gxt';
export default function(owner) {
console.log('root-template init', owner);
return function(rootState) {
// console.log('root-template - render', [this], [...arguments]);
// temp1.root.template
// console.log(...arguments);
// return function() {
// console.log(...arguments);
// return $_fin([...rootState.root.template()], this);
// }
// debugger;
const state = rootState.root.ref;
console.log('rootState', state);
return hbs`
{{log 'root-template-create' this rootState}}
{{#let (component rootState.root.template state=state root=true) as |Layout|}}
<Layout />
{{/let}}
`;
}
}
Loading
Loading