Skip to content

Commit

Permalink
[feat]: nested rendering contexts
Browse files Browse the repository at this point in the history
  • Loading branch information
lifeart committed Dec 28, 2024
1 parent 0e38f95 commit 8e1c800
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 2 deletions.
6 changes: 5 additions & 1 deletion src/utils/component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import type {
Invoke,
ComponentReturn,
} from '@glint/template/-private/integration';
import { api } from '@/utils/dom-api';
import { api, RENDERING_CONTEXT } from '@/utils/dom-api';
import {
isFn,
$template,
Expand All @@ -24,6 +24,7 @@ import {
PARENT_GRAPH,
} from './shared';
import { addChild, getRoot, setRoot } from './dom';
import { provideContext } from './context';

export type ComponentRenderTarget =
| HTMLElement
Expand Down Expand Up @@ -109,6 +110,9 @@ export function renderComponent(
}
}

console.log('context provided', getRoot(), api);
provideContext(getRoot()!, RENDERING_CONTEXT, api);

if ($template in component && isFn(component[$template])) {
return renderComponent(
component[$template](),
Expand Down
2 changes: 2 additions & 0 deletions src/utils/control-flow/if.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
isFn,
isPrimitive,
isTagLike,
addToTree
} from '@/utils/shared';
import { opcodeFor } from '@/utils/vm';

Expand Down Expand Up @@ -48,6 +49,7 @@ export class IfCondition {
this.setupCondition(maybeCondition);
this.trueBranch = trueBranch;
this.falseBranch = falseBranch;
addToTree(parentContext, this);
this.destructors.push(opcodeFor(this.condition, this.syncState.bind(this)));
associateDestroyable(parentContext, [this.destroy.bind(this)]);
if (IS_DEV_MODE) {
Expand Down
2 changes: 2 additions & 0 deletions src/utils/control-flow/list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import {
isPrimitive,
isTagLike,
LISTS_FOR_HMR,
addToTree,
} from '@/utils/shared';
import { isRehydrationScheduled } from '@/utils/ssr/rehydration';

Expand Down Expand Up @@ -98,6 +99,7 @@ export class BasicListComponent<T extends { id: number }> {
topMarker: Comment,
) {
this.ItemComponent = ItemComponent;
addToTree(ctx, this);
this.parentCtx = ctx;
const mainNode = outlet;
this[$nodes] = [];
Expand Down
2 changes: 2 additions & 0 deletions src/utils/dom-api.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import { getNodeCounter, incrementNodeCounter } from '@/utils/dom';
import { IN_SSR_ENV, noop } from './shared';

export const RENDERING_CONTEXT = Symbol('RENDERING_CONTEXT');

let $doc =
typeof document !== 'undefined'
? document
Expand Down
25 changes: 24 additions & 1 deletion src/utils/dom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import {
destroy,
registerDestructor,
} from './glimmer/destroyable';
import { api, getDocument } from '@/utils/dom-api';
import { api as HTMLAPI, getDocument, RENDERING_CONTEXT } from '@/utils/dom-api';
import {
isFn,
isPrimitive,
Expand All @@ -47,6 +47,7 @@ import { isRehydrationScheduled } from './ssr/rehydration';
import { createHotReload } from './hmr';
import { IfCondition } from './control-flow/if';
import { CONSTANTS } from '../../plugins/symbols';
import { getContext } from './context';

type RenderableType = Node | ComponentReturnType | string | number;
type ShadowRootMode = 'open' | 'closed' | null;
Expand Down Expand Up @@ -82,6 +83,7 @@ const $_className = 'className';

let unstableWrapperId: number = 0;
let ROOT: Component<any> | null = null;
let api = HTMLAPI;

export const $_MANAGERS = {
component: {
Expand Down Expand Up @@ -494,6 +496,11 @@ function _DOM(
ctx: any,
): Node {
NODE_COUNTER++;
api = getContext<typeof HTMLAPI>(ctx, RENDERING_CONTEXT)!;
if (!api) {
debugger;
api = getContext<typeof HTMLAPI>(ctx, RENDERING_CONTEXT)!;
}
const element = api.element(tag);
if (IS_DEV_MODE) {
$DEBUG_REACTIVE_CONTEXTS.push(`${tag}`);
Expand Down Expand Up @@ -626,6 +633,7 @@ export function $_inElement(
) {
return component(
function UnstableChildWrapper(this: Component<any>) {
$_GET_ARGS(this, arguments);
if (IS_DEV_MODE) {
// @ts-expect-error construct signature
this.debugName = `InElement-${unstableWrapperId++}`;
Expand Down Expand Up @@ -660,6 +668,9 @@ export function $_ucw(
) {
return component(
function UnstableChildWrapper(this: Component<any>) {
// console.log(this, ...arguments);
$_GET_ARGS(this, arguments);
// debugger;
if (IS_DEV_MODE) {
// @ts-expect-error construct signature
this.debugName = `UnstableChildWrapper-${unstableWrapperId++}`;
Expand Down Expand Up @@ -837,6 +848,7 @@ function _component(
fw: FwType,
ctx: Component<any>,
) {
args['_context'] = ctx;
let comp = _comp;
if (WITH_EMBER_INTEGRATION) {
if ($_MANAGERS.component.canHandle(_comp)) {
Expand Down Expand Up @@ -897,7 +909,10 @@ function _component(
}
if (instance.ctx !== null) {
// for now we adding only components with context
// debugger;
addToTree(ctx, instance.ctx);
// addToTree(ctx, instance);

if (IS_DEV_MODE) {
setBounds(instance);
}
Expand Down Expand Up @@ -1163,6 +1178,13 @@ const ArgProxyHandler = {
};
export function $_GET_ARGS(ctx: any, args: any) {
ctx[$args] = ctx[$args] || args[0] || {};
const parentContext = ctx[$args]['_context'];
if (parentContext) {
// console.log('context', parentContext, ctx);
addToTree(parentContext, ctx);
} else {
addToTree(getRoot()!, ctx);
}
}
export function $_GET_SLOTS(ctx: any, args: any) {
return (args[0] || {})[$SLOTS_SYMBOL] || ctx[$args]?.[$SLOTS_SYMBOL] || {};
Expand Down Expand Up @@ -1238,6 +1260,7 @@ export function $_dc(
const destructor = opcodeFor(_cmp, (value: any) => {
if (typeof value !== 'function') {
result = value;
addToTree(ctx, result);
return;
}
if (value !== ref) {
Expand Down
28 changes: 28 additions & 0 deletions src/utils/provider.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
import { Component } from "./component";
import { $template } from "./shared";
import { provideContext } from './context';
import { getDocument, RENDERING_CONTEXT } from "./dom-api";

// SVG DOM API
const svgDomApi = {
element: (tagName: string): SVGElement => {
return getDocument().createElementNS('http://www.w3.org/2000/svg', tagName) as SVGElement;
},
setAttribute: (element: SVGElement, name: string, value: string) => {
element.setAttribute(name, value);
},
append: (parent: SVGElement, child: SVGElement) => {
parent.appendChild(child);
},
};

export class SvgProvider extends Component {
constructor() {
super(...arguments);
provideContext(this, RENDERING_CONTEXT, svgDomApi);

}
[$template]() {
return [];
}
}
3 changes: 3 additions & 0 deletions src/utils/shared.ts
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,9 @@ export function addToTree(
node: Component<any>,
debugName?: string,
) {
// if (node.toString() === '[object Object]') {
// debugger;
// }
if (IS_DEV_MODE) {
if ('nodeType' in node) {
throw new Error('invalid node');
Expand Down

0 comments on commit 8e1c800

Please sign in to comment.