Skip to content

Commit

Permalink
[REFACTOR] Extract environment variables into global context
Browse files Browse the repository at this point in the history
There are a number of environment variables that are currently threaded
through glimmer that are:

1. Only environment variables for compatibility reasons (e.g. legacy
   Ember compat)
2. Never expected to change over the lifetime of an append
3. Never expected to differ between different apps or render trees in
   the same context.

This PR consolidates these into a single global context, exported from
`@glimmer/global-context`, which is set once by the embedding
environment before rendering. It also upstreams the logic for
`protocolForUrl`, which was not specific to Ember, and simplifies
the `attributeFor` logic to be as minimal as possible an interface for
Ember.
  • Loading branch information
Chris Garrett committed Aug 21, 2020
1 parent 280f581 commit 79ff403
Show file tree
Hide file tree
Showing 38 changed files with 636 additions and 537 deletions.
15 changes: 8 additions & 7 deletions packages/@glimmer/benchmark-env/package.json
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
{
"name": "@glimmer/benchmark-env",
"version": "0.56.1",
"version": "0.58.0",
"private": true,
"repository": "https://github.com/glimmerjs/glimmer-vm/tree/master/packages/@glimmer/benchmark-env",
"dependencies": {
"@glimmer/reference": "^0.56.1",
"@glimmer/runtime": "^0.56.1",
"@glimmer/validator": "^0.56.1",
"@glimmer/util": "^0.56.1",
"@glimmer/interfaces": "^0.56.1",
"@glimmer/opcode-compiler": "^0.56.1",
"@glimmer/global-context": "^0.58.0",
"@glimmer/reference": "^0.58.0",
"@glimmer/runtime": "^0.58.0",
"@glimmer/validator": "^0.58.0",
"@glimmer/util": "^0.58.0",
"@glimmer/interfaces": "^0.58.0",
"@glimmer/opcode-compiler": "^0.58.0",
"@simple-dom/interface": "^1.4.0"
},
"devDependencies": {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ class BasicComponentManager
args: VMArguments | null
) {
const instance = new Component(argsProxy(args === null ? EMPTY_ARGS : args.capture()));
const self = new ComponentRootReference(instance, env);
const self = new ComponentRootReference(instance);
return { env, instance, self };
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { EnvironmentDelegate, setScheduleDestroyed, setScheduleDestroy } from '@glimmer/runtime';
import { Destroyable, Destructor } from '@glimmer/interfaces';
import { EnvironmentDelegate } from '@glimmer/runtime';
import { Destroyable, Destructor, RenderResult } from '@glimmer/interfaces';
import setGlobalContext from '@glimmer/global-context';

type Queue = (() => void)[];

Expand All @@ -11,17 +12,69 @@ function flush(queue: Queue) {
queue.length = 0;
}

setScheduleDestroy(<T extends Destroyable>(destroyable: T, destructor: Destructor<T>) => {
scheduledDestructors.push(() => destructor(destroyable));
});
let result: RenderResult;
let resolveRender: () => void;

export function registerResult(_result: RenderResult, _resolveRender: () => void) {
result = _result;
resolveRender = _resolveRender;
}

let revalidateScheduled = false;

setGlobalContext({
scheduleRevalidate() {
if (!revalidateScheduled) {
Promise.resolve().then(() => {
const { env } = result;
env.begin();
result.rerender();
revalidateScheduled = false;
env.commit();
// only resolve if commit didn't dirty again
if (!revalidateScheduled && resolveRender !== undefined) {
resolveRender();
}
});
}
},

getProp(obj: unknown, prop: string) {
return (obj as Record<string, unknown>)[prop];
},

setProp(obj: unknown, prop: string, value) {
(obj as Record<string, unknown>)[prop] = value;
},

getPath(obj: unknown, path: string) {
return (obj as Record<string, unknown>)[path];
},

toBool(value) {
return Boolean(value);
},

toIterator() {
return null;
},

warnIfStyleNotTrusted() {},

scheduleDestroy<T extends Destroyable>(destroyable: T, destructor: Destructor<T>) {
scheduledDestructors.push(() => destructor(destroyable));
},

setScheduleDestroyed((fn: () => void) => {
scheduledFinalizers.push(fn);
scheduleDestroyed(fn: () => void) {
scheduledFinalizers.push(fn);
},
});

export default function createEnvDelegate(isInteractive: boolean): EnvironmentDelegate {
return {
isInteractive,
extra: undefined,
onTransactionBegin() {},
onTransactionCommit() {
flush(scheduledDestructors);
flush(scheduledFinalizers);
Expand Down
20 changes: 6 additions & 14 deletions packages/@glimmer/benchmark-env/src/benchmark/if-helper.ts
Original file line number Diff line number Diff line change
@@ -1,24 +1,16 @@
import { VMArguments, VM } from '@glimmer/interfaces';
import {
Reference,
PathReference,
CachedReference,
PropertyReference,
TemplateReferenceEnvironment,
} from '@glimmer/reference';
import { VMArguments } from '@glimmer/interfaces';
import { Reference, PathReference, CachedReference, PropertyReference } from '@glimmer/reference';

class IfHelperReference extends CachedReference<unknown> {
condition: Reference;
truthyValue: Reference;
falsyValue: Reference | undefined;
env: TemplateReferenceEnvironment;

constructor({ positional }: VMArguments, env: TemplateReferenceEnvironment) {
constructor({ positional }: VMArguments) {
super();
this.condition = positional.at(0);
this.truthyValue = positional.at(1);
this.falsyValue = positional.length > 2 ? positional.at(2) : undefined;
this.env = env;
}

compute() {
Expand All @@ -33,10 +25,10 @@ class IfHelperReference extends CachedReference<unknown> {
}

get(key: string): PathReference {
return new PropertyReference(this, key, this.env);
return new PropertyReference(this, key);
}
}

export default function ifHelper(args: VMArguments, vm: VM): PathReference {
return new IfHelperReference(args, vm.env);
export default function ifHelper(args: VMArguments): PathReference {
return new IfHelperReference(args);
}
25 changes: 7 additions & 18 deletions packages/@glimmer/benchmark-env/src/benchmark/render-benchmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import {
ComponentDefinition,
CompilableProgram,
} from '@glimmer/interfaces';
import { setPropertyDidChange } from '@glimmer/validator';
import { ComponentRootReference, PathReference } from '@glimmer/reference';
import {
NewElementBuilder,
Expand All @@ -15,7 +14,7 @@ import {
renderJitComponent,
} from '@glimmer/runtime';

import createEnvDelegate from './create-env-delegate';
import createEnvDelegate, { registerResult } from './create-env-delegate';
import { measureRender } from './util';
import { UpdateBenchmark } from '../interfaces';

Expand All @@ -29,6 +28,7 @@ export default async function renderBenchmark(
isInteractive = true
): Promise<UpdateBenchmark> {
let resolveRender: (() => void) | undefined;

await measureRender('render', 'renderStart', 'renderEnd', () => {
const document = element.ownerDocument;
const envDelegate = createEnvDelegate(isInteractive);
Expand All @@ -43,7 +43,7 @@ export default async function renderBenchmark(
const env = runtime.env;
const cursor = { element, nextSibling: null };
const treeBuilder = NewElementBuilder.forInitialRender(env, cursor);
const rootRef = new ComponentRootReference(root, env);
const rootRef = new ComponentRootReference(root);

const args: Dict<PathReference> = {};
for (const key of Object.keys(root)) {
Expand All @@ -55,21 +55,10 @@ export default async function renderBenchmark(
renderJitComponent(runtime, treeBuilder, context, component, layout, args)
);

let scheduled = false;
setPropertyDidChange(() => {
if (!scheduled) {
Promise.resolve().then(() => {
const { env } = result;
env.begin();
result.rerender();
scheduled = false;
env.commit();
// only resolve if commit didn't dirty again
if (!scheduled && resolveRender !== undefined) {
resolveRender();
resolveRender = undefined;
}
});
registerResult(result, () => {
if (resolveRender !== undefined) {
resolveRender();
resolveRender = undefined;
}
});
});
Expand Down
Loading

0 comments on commit 79ff403

Please sign in to comment.