diff --git a/benchmark/benchmarks/krausest/vite.config.mts b/benchmark/benchmarks/krausest/vite.config.mts index 7a5bdb1c74..b08de0cf6b 100644 --- a/benchmark/benchmarks/krausest/vite.config.mts +++ b/benchmark/benchmarks/krausest/vite.config.mts @@ -22,7 +22,6 @@ export default defineConfig({ resolve: { alias: { '@glimmer-workspace/benchmark-env': '@glimmer-workspace/benchmark-env/index.ts', - '@glimmer/debug': packagePath('@glimmer/debug'), '@glimmer/runtime': packagePath('@glimmer/runtime'), '@/components': path.join(currentPath, 'lib', 'components'), '@/utils': path.join(currentPath, 'lib', 'utils'), diff --git a/bin/build-verify.mjs b/bin/build-verify.mjs index 0fc68c1211..50dd6ede64 100644 --- a/bin/build-verify.mjs +++ b/bin/build-verify.mjs @@ -21,9 +21,13 @@ const FORBIDDEN = [ 'CheckOr', 'CheckFunction', 'CheckObject', + + '@glimmer/debug', + '@glimmer/constants', + '@glimmer/debug-util', ]; -const IGNORED_DIRS = [`@glimmer/debug`]; +const IGNORED_DIRS = [`@glimmer/debug`, `@glimmer/constants`, `@glimmer/debug-util`]; let files = await globby(resolve(currentDir, '../../packages/**/dist/**/index.js'), { ignore: ['node_modules', '**/node_modules'], diff --git a/packages/@glimmer-workspace/build/lib/config.js b/packages/@glimmer-workspace/build/lib/config.js index 326354a295..a49269c842 100644 --- a/packages/@glimmer-workspace/build/lib/config.js +++ b/packages/@glimmer-workspace/build/lib/config.js @@ -114,7 +114,13 @@ export function typescript(pkg, config) { const EXTERNAL_OPTIONS = [ [ 'is', - ['tslib', '@glimmer/local-debug-flags', '@glimmer/debug', '@glimmer/debug-util'], + [ + 'tslib', + '@glimmer/local-debug-flags', + '@glimmer/constants', + '@glimmer/debug', + '@glimmer/debug-util', + ], 'inline', ], ['is', ['@handlebars/parser', 'simple-html-tokenizer', 'babel-plugin-debug-macros'], 'external'], diff --git a/packages/@glimmer-workspace/integration-tests/lib/dom/simple-utils.ts b/packages/@glimmer-workspace/integration-tests/lib/dom/simple-utils.ts index ba7f1ddd14..54a72aff87 100644 --- a/packages/@glimmer-workspace/integration-tests/lib/dom/simple-utils.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/dom/simple-utils.ts @@ -1,3 +1,9 @@ +import type { + COMMENT_NODE, + DOCUMENT_FRAGMENT_NODE, + DOCUMENT_NODE, + TEXT_NODE, +} from '@glimmer/constants'; import type { Maybe, Nullable, @@ -10,8 +16,8 @@ import type { SimpleNode, SimpleText, } from '@glimmer/interfaces'; -import type { COMMENT_NODE, DOCUMENT_FRAGMENT_NODE, DOCUMENT_NODE, TEXT_NODE } from '@glimmer/util'; -import { clearElement, ELEMENT_NODE, INSERT_AFTER_BEGIN } from '@glimmer/util'; +import { ELEMENT_NODE, INSERT_AFTER_BEGIN } from '@glimmer/constants'; +import { clearElement } from '@glimmer/util'; import Serializer from '@simple-dom/serializer'; import voidMap from '@simple-dom/void-map'; diff --git a/packages/@glimmer-workspace/integration-tests/lib/modes/rehydration/builder.ts b/packages/@glimmer-workspace/integration-tests/lib/modes/rehydration/builder.ts index 032ec9a5b1..5d02075f8b 100644 --- a/packages/@glimmer-workspace/integration-tests/lib/modes/rehydration/builder.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/modes/rehydration/builder.ts @@ -1,6 +1,6 @@ import type { Cursor, ElementBuilder, Environment, SimpleNode } from '@glimmer/interfaces'; +import { COMMENT_NODE, ELEMENT_NODE } from '@glimmer/constants'; import { RehydrateBuilder } from '@glimmer/runtime'; -import { COMMENT_NODE, ELEMENT_NODE } from '@glimmer/util'; export class DebugRehydrationBuilder extends RehydrateBuilder { clearedNodes: SimpleNode[] = []; diff --git a/packages/@glimmer-workspace/integration-tests/lib/setup-harness.ts b/packages/@glimmer-workspace/integration-tests/lib/setup-harness.ts index 485f7539f9..5ccb61ad1d 100644 --- a/packages/@glimmer-workspace/integration-tests/lib/setup-harness.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/setup-harness.ts @@ -1,26 +1,60 @@ /* eslint-disable no-console */ +import type { Expand } from '@glimmer/interfaces'; import { debug } from '@glimmer/validator'; import { autoRegister } from 'js-reporters'; +import { default as QUnit } from 'qunit'; export async function setupQunit() { - const qunit = await import('qunit'); + const qunitLib: QUnit = await import('qunit'); await import('qunit/qunit/qunit.css'); + const testing = Testing.withConfig( + { + id: 'smoke_tests', + label: 'Smoke Tests', + tooltip: 'Enable Smoke Tests', + }, + { + id: 'ci', + label: 'CI Mode', + tooltip: + 'CI mode emits tap output and makes tests run faster by sacrificing UI responsiveness', + }, + { + id: 'enable_internals_logging', + label: 'Log Deep Internals', + tooltip: 'Logs internals that are used in the development of the trace logs', + }, + + { + id: 'enable_trace_logging', + label: 'Trace Logs', + tooltip: 'Trace logs emit information about the internal VM state', + }, + + { + id: 'enable_subtle_logging', + label: '+ Subtle', + tooltip: + 'Subtle logs include unchanged information and other details not necessary for normal debugging', + }, + + { + id: 'enable_trace_explanations', + label: '+ Explanations', + tooltip: 'Also explain the trace logs', + } + ); + const runner = autoRegister(); - // @ts-expect-error qunit types don't expose "reporters" - const tap = qunit.reporters.tap; - tap.init(runner, { log: console.info }); - - QUnit.config.urlConfig.push({ - id: 'smoke_tests', - label: 'Enable Smoke Tests', - tooltip: 'Enable Smoke Tests', - }); - QUnit.config.urlConfig.push({ - id: 'ci', - label: 'Enable CI Mode', - tooltip: 'CI mode makes tests run faster by sacrificing UI responsiveness', + testing.begin(() => { + if (testing.config.ci) { + // eslint-disable-next-line @typescript-eslint/ban-ts-comment + // @ts-ignore + const tap = qunitLib.reporters.tap; + tap.init(runner, { log: console.info }); + } }); await Promise.resolve(); @@ -34,7 +68,7 @@ export async function setupQunit() { console.log(`[HARNESS] ci=${hasFlag('ci')}`); - QUnit.testStart(() => { + testing.testStart(() => { debug.resetTrackingTransaction?.(); }); @@ -52,7 +86,7 @@ export async function setupQunit() { }); let start = performance.now(); - qunit.testDone(async () => { + qunitLib.testDone(async () => { let gap = performance.now() - start; if (gap > 200) { await pause(); @@ -60,28 +94,11 @@ export async function setupQunit() { } }); - qunit.moduleDone(pause); + qunitLib.moduleDone(pause); } - // @ts-expect-error missing in types, does exist: https://api.qunitjs.com/callbacks/QUnit.on/#the-testend-event - QUnit.on('testEnd', (testEnd) => { - if (testEnd.status === 'failed') { - testEnd.errors.forEach((assertion: any) => { - console.error(assertion.stack); - // message: speedometer - // actual: 75 - // expected: 88 - // stack: at dmc.test.js:12 - }); - } - }); - - qunit.done(({ failed }) => { - if (failed > 0) { - console.log('[HARNESS] fail'); - } else { - console.log('[HARNESS] done'); - } + qunitLib.done(() => { + console.log('[HARNESS] done'); }); return { @@ -89,7 +106,74 @@ export async function setupQunit() { }; } +class Testing { + static withConfig(...configs: C): Testing> { + return new Testing(withConfig(...configs)); + } + + readonly #qunit: Q; + + constructor(qunit: Q) { + this.#qunit = qunit; + } + + get config(): Q['config'] { + return this.#qunit.config; + } + + readonly begin = (begin: (details: QUnit.BeginDetails) => void | Promise): void => { + this.#qunit.begin(begin); + }; + + readonly testStart = ( + callback: (details: QUnit.TestStartDetails) => void | Promise + ): void => { + this.#qunit.testStart(callback); + }; +} + function hasFlag(flag: string): boolean { + return hasSpecificFlag(flag); +} + +function hasSpecificFlag(flag: string): boolean { let location = typeof window !== 'undefined' && window.location; return location && new RegExp(`[?&]${flag}`).test(location.search); } + +// eslint-disable-next-line unused-imports/no-unused-vars +function getSpecificFlag(flag: string): string | undefined { + let location = typeof window !== 'undefined' && window.location; + if (!location) { + return undefined; + } + + const matches = new RegExp(`[?&]${flag}=([^&]*)`).exec(location.search); + return matches ? matches[1] : undefined; +} + +interface UrlConfig { + id: string; + label?: string | undefined; + tooltip?: string | undefined; + value?: string | string[] | { [key: string]: string } | undefined; +} + +type WithConfig = typeof QUnit & { + config: QUnit['config'] & { + [P in C[number]['id']]: string | undefined; + }; +}; + +function withConfig(...configs: C): Expand> { + for (let config of configs) { + QUnit.config.urlConfig.push(config); + } + + const index = QUnit.config.urlConfig.findIndex((c) => c.id === 'noglobals'); + if (index !== -1) { + QUnit.config.urlConfig.splice(index, 1); + } + + return QUnit as any; +} diff --git a/packages/@glimmer-workspace/integration-tests/lib/snapshot.ts b/packages/@glimmer-workspace/integration-tests/lib/snapshot.ts index 74d122431b..c23ae3b5ad 100644 --- a/packages/@glimmer-workspace/integration-tests/lib/snapshot.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/snapshot.ts @@ -1,7 +1,7 @@ import type { Nullable, SimpleElement, SimpleNode } from '@glimmer/interfaces'; import type { EndTag, Token } from 'simple-html-tokenizer'; +import { COMMENT_NODE, TEXT_NODE } from '@glimmer/constants'; import { castToSimple, unwrap } from '@glimmer/debug-util'; -import { COMMENT_NODE, TEXT_NODE } from '@glimmer/util'; import { tokenize } from 'simple-html-tokenizer'; import { replaceHTML, toInnerHTML } from './dom/simple-utils'; diff --git a/packages/@glimmer-workspace/integration-tests/lib/suites/initial-render.ts b/packages/@glimmer-workspace/integration-tests/lib/suites/initial-render.ts index 4c3b3601b7..34b2e60fe7 100644 --- a/packages/@glimmer-workspace/integration-tests/lib/suites/initial-render.ts +++ b/packages/@glimmer-workspace/integration-tests/lib/suites/initial-render.ts @@ -1,6 +1,7 @@ import type { SimpleElement } from '@glimmer/interfaces'; +import { NS_SVG } from '@glimmer/constants'; import { castToBrowser, checkNode, unwrap } from '@glimmer/debug-util'; -import { NS_SVG, strip } from '@glimmer/util'; +import { strip } from '@glimmer/util'; import { assertNodeTagName } from '../dom/assertions'; import { firstElementChild, getElementsByTagName } from '../dom/simple-utils'; diff --git a/packages/@glimmer-workspace/integration-tests/package.json b/packages/@glimmer-workspace/integration-tests/package.json index dccfc93a07..04ffebab6f 100644 --- a/packages/@glimmer-workspace/integration-tests/package.json +++ b/packages/@glimmer-workspace/integration-tests/package.json @@ -34,6 +34,7 @@ "simple-html-tokenizer": "^0.5.11" }, "devDependencies": { + "@glimmer/constants": "workspace:*", "@glimmer/debug-util": "workspace:*", "@glimmer/local-debug-flags": "workspace:*", "@types/js-reporters": "workspace:*", diff --git a/packages/@glimmer-workspace/integration-tests/test/attributes-test.ts b/packages/@glimmer-workspace/integration-tests/test/attributes-test.ts index 3ecfe00f09..7ff6452e74 100644 --- a/packages/@glimmer-workspace/integration-tests/test/attributes-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/attributes-test.ts @@ -1,7 +1,7 @@ import type { SimpleElement } from '@glimmer/interfaces'; +import { NS_SVG } from '@glimmer/constants'; import { castToBrowser, expect } from '@glimmer/debug-util'; import { normalizeProperty } from '@glimmer/runtime'; -import { NS_SVG } from '@glimmer/util'; import { assertingElement, hasAttribute, jitSuite, RenderTest, test, tracked } from '..'; diff --git a/packages/@glimmer-workspace/integration-tests/test/chaos-rehydration-test.ts b/packages/@glimmer-workspace/integration-tests/test/chaos-rehydration-test.ts index 6586bc9524..8925838d82 100644 --- a/packages/@glimmer-workspace/integration-tests/test/chaos-rehydration-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/chaos-rehydration-test.ts @@ -1,6 +1,7 @@ import type { Dict, Nullable, SimpleElement } from '@glimmer/interfaces'; +import { COMMENT_NODE, ELEMENT_NODE } from '@glimmer/constants'; import { castToBrowser, castToSimple, expect } from '@glimmer/debug-util'; -import { COMMENT_NODE, ELEMENT_NODE, isObject, LOCAL_LOGGER } from '@glimmer/util'; +import { isObject, LOCAL_LOGGER } from '@glimmer/util'; import type { ComponentBlueprint, Content } from '..'; @@ -101,7 +102,7 @@ abstract class AbstractChaosMonkeyTest extends RenderTest { } if (shouldLog) { - LOCAL_LOGGER.log( + LOCAL_LOGGER.debug( `${removedNodeDisplay} was removed;\noriginal: ${original}\nupdated: ${element.innerHTML}` ); } diff --git a/packages/@glimmer-workspace/integration-tests/test/updating-content-matrix-test.ts b/packages/@glimmer-workspace/integration-tests/test/updating-content-matrix-test.ts index eb4f6beb4c..4085efb46b 100644 --- a/packages/@glimmer-workspace/integration-tests/test/updating-content-matrix-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/updating-content-matrix-test.ts @@ -1,6 +1,6 @@ import type { SimpleElement, SimpleNode } from '@glimmer/interfaces'; import type { SafeString } from '@glimmer/runtime'; -import { NS_SVG } from '@glimmer/util'; +import { NS_SVG } from '@glimmer/constants'; import type { RenderTestConstructor } from '..'; import type RenderDelegate from '../lib/render-delegate'; diff --git a/packages/@glimmer-workspace/integration-tests/test/updating-svg-test.ts b/packages/@glimmer-workspace/integration-tests/test/updating-svg-test.ts index c13195a51b..010e4d68e1 100644 --- a/packages/@glimmer-workspace/integration-tests/test/updating-svg-test.ts +++ b/packages/@glimmer-workspace/integration-tests/test/updating-svg-test.ts @@ -1,5 +1,5 @@ import type { SimpleElement } from '@glimmer/interfaces'; -import { NS_HTML, NS_SVG, NS_XLINK } from '@glimmer/util'; +import { NS_HTML, NS_SVG, NS_XLINK } from '@glimmer/constants'; import { assertNodeTagName, jitSuite, RenderTest, test } from '..'; import { assert } from './support'; diff --git a/packages/@glimmer/compiler/index.ts b/packages/@glimmer/compiler/index.ts index b4a5d141f4..72dbcad463 100644 --- a/packages/@glimmer/compiler/index.ts +++ b/packages/@glimmer/compiler/index.ts @@ -7,7 +7,7 @@ export { s, unicode, } from './lib/builder/builder'; -export { Builder, type BuilderStatement } from './lib/builder/builder-interface'; +export { type BuilderStatement } from './lib/builder/builder-interface'; export { defaultId, precompile, precompileJSON, type PrecompileOptions } from './lib/compiler'; // exported only for tests! diff --git a/packages/@glimmer/compiler/lib/builder/builder-interface.ts b/packages/@glimmer/compiler/lib/builder/builder-interface.ts index fb84a6a33f..4211413085 100644 --- a/packages/@glimmer/compiler/lib/builder/builder-interface.ts +++ b/packages/@glimmer/compiler/lib/builder/builder-interface.ts @@ -1,4 +1,39 @@ +import type { VariableKind } from '@glimmer/constants'; import type { Dict, DictValue, Nullable, PresentArray } from '@glimmer/interfaces'; +import { + APPEND_EXPR_HEAD, + APPEND_PATH_HEAD, + ARG_VAR, + BLOCK_HEAD, + BLOCK_VAR, + BUILDER_APPEND, + BUILDER_COMMENT, + BUILDER_CONCAT, + BUILDER_DYNAMIC_COMPONENT, + BUILDER_GET, + BUILDER_HAS_BLOCK, + BUILDER_HAS_BLOCK_PARAMS, + BUILDER_LITERAL, + BUILDER_MODIFIER, + CALL_EXPR, + CALL_HEAD, + COMMENT_HEAD, + CONCAT_EXPR, + DYNAMIC_COMPONENT_HEAD, + ELEMENT_HEAD, + FREE_VAR, + GET_PATH_EXPR, + GET_VAR_EXPR, + HAS_BLOCK_EXPR, + HAS_BLOCK_PARAMS_EXPR, + KEYWORD_HEAD, + LITERAL_EXPR, + LITERAL_HEAD, + LOCAL_VAR, + MODIFIER_HEAD, + SPLAT_HEAD, + THIS_VAR, +} from '@glimmer/constants'; import { expect, isPresentArray } from '@glimmer/debug-util'; import { assertNever, dict } from '@glimmer/util'; @@ -13,7 +48,7 @@ export type NormalizedHash = Dict; export type NormalizedBlock = NormalizedStatement[]; export type NormalizedBlocks = Dict; export type NormalizedAttrs = Dict; -export type NormalizedAttr = HeadKind.Splat | NormalizedExpression; +export type NormalizedAttr = SPLAT_HEAD | NormalizedExpression; export interface NormalizedElement { name: string; @@ -27,28 +62,6 @@ export interface NormalizedAngleInvocation { block: Nullable; } -export enum HeadKind { - Block = 'Block', - Call = 'Call', - Element = 'Element', - AppendPath = 'AppendPath', - AppendExpr = 'AppendExpr', - Literal = 'Literal', - Modifier = 'Modifier', - DynamicComponent = 'DynamicComponent', - Comment = 'Comment', - Splat = 'Splat', - Keyword = 'Keyword', -} - -export enum VariableKind { - Local = 'Local', - Free = 'Free', - Arg = 'Arg', - Block = 'Block', - This = 'This', -} - export interface Variable { kind: VariableKind; name: string; @@ -68,19 +81,19 @@ export interface Path { } export interface AppendExpr { - kind: HeadKind.AppendExpr; + kind: APPEND_EXPR_HEAD; expr: NormalizedExpression; trusted: boolean; } export interface AppendPath { - kind: HeadKind.AppendPath; + kind: APPEND_PATH_HEAD; path: NormalizedPath; trusted: boolean; } export interface NormalizedKeywordStatement { - kind: HeadKind.Keyword; + kind: KEYWORD_HEAD; name: string; params: Nullable; hash: Nullable; @@ -90,14 +103,14 @@ export interface NormalizedKeywordStatement { export type NormalizedStatement = | { - kind: HeadKind.Call; + kind: CALL_HEAD; head: NormalizedHead; params: Nullable; hash: Nullable; trusted: boolean; } | { - kind: HeadKind.Block; + kind: BLOCK_HEAD; head: NormalizedHead; params: Nullable; hash: Nullable; @@ -106,18 +119,18 @@ export type NormalizedStatement = } | NormalizedKeywordStatement | { - kind: HeadKind.Element; + kind: ELEMENT_HEAD; name: string; attrs: NormalizedAttrs; block: NormalizedBlock; } - | { kind: HeadKind.Comment; value: string } - | { kind: HeadKind.Literal; value: string } + | { kind: COMMENT_HEAD; value: string } + | { kind: LITERAL_HEAD; value: string } | AppendPath | AppendExpr - | { kind: HeadKind.Modifier; params: NormalizedParams; hash: Nullable } + | { kind: MODIFIER_HEAD; params: NormalizedParams; hash: Nullable } | { - kind: HeadKind.DynamicComponent; + kind: DYNAMIC_COMPONENT_HEAD; expr: NormalizedExpression; hash: Nullable; block: NormalizedBlock; @@ -143,15 +156,15 @@ export function normalizeAppendHead( head: NormalizedHead, trusted: boolean ): AppendExpr | AppendPath { - if (head.type === ExpressionKind.GetPath) { + if (head.type === GET_PATH_EXPR) { return { - kind: HeadKind.AppendPath, + kind: APPEND_PATH_HEAD, path: head, trusted, }; } else { return { - kind: HeadKind.AppendExpr, + kind: APPEND_EXPR_HEAD, expr: head, trusted, }; @@ -198,7 +211,7 @@ export function normalizeSugaryArrayStatement( } return { - kind: HeadKind.Call, + kind: CALL_HEAD, head: normalizeCallHead(name), params, hash, @@ -216,7 +229,7 @@ export function normalizeSugaryArrayStatement( } = normalizeBuilderBlockStatement(statement as BuilderBlockStatement); return { - kind: HeadKind.Block, + kind: BLOCK_HEAD, head: path, params, hash, @@ -232,7 +245,7 @@ export function normalizeSugaryArrayStatement( ); return { - kind: HeadKind.Keyword, + kind: KEYWORD_HEAD, name, params, hash, @@ -257,7 +270,7 @@ export function normalizeSugaryArrayStatement( } return { - kind: HeadKind.Element, + kind: ELEMENT_HEAD, name: expect(extractElement(name), `BUG: expected ${name} to look like a tag name`), attrs, block, @@ -271,37 +284,37 @@ export function normalizeSugaryArrayStatement( function normalizeVerboseStatement(statement: VerboseStatement): NormalizedStatement { switch (statement[0]) { - case Builder.Literal: { + case BUILDER_LITERAL: { return { - kind: HeadKind.Literal, + kind: LITERAL_HEAD, value: statement[1], }; } - case Builder.Append: { + case BUILDER_APPEND: { return normalizeAppendExpression(statement[1], statement[2]); } - case Builder.Modifier: { + case BUILDER_MODIFIER: { return { - kind: HeadKind.Modifier, + kind: MODIFIER_HEAD, params: normalizeParams(statement[1]), hash: normalizeHash(statement[2]), }; } - case Builder.DynamicComponent: { + case BUILDER_DYNAMIC_COMPONENT: { return { - kind: HeadKind.DynamicComponent, + kind: DYNAMIC_COMPONENT_HEAD, expr: normalizeExpression(statement[1]), hash: normalizeHash(statement[2]), block: normalizeBlock(statement[3]), }; } - case Builder.Comment: { + case BUILDER_COMMENT: { return { - kind: HeadKind.Comment, + kind: COMMENT_HEAD, value: statement[1], }; } @@ -333,7 +346,7 @@ function normalizePath(head: string, tail: string[] = []): NormalizedHead { if (isPresentArray(tail)) { return { - type: ExpressionKind.GetPath, + type: GET_PATH_EXPR, path: { head: pathHead, tail, @@ -341,7 +354,7 @@ function normalizePath(head: string, tail: string[] = []): NormalizedHead { }; } else { return { - type: ExpressionKind.GetVar, + type: GET_VAR_EXPR, variable: pathHead, }; } @@ -355,9 +368,9 @@ function normalizeDottedPath(whole: string): NormalizedHead { const variable: Variable = { kind, name, mode: 'loose' }; if (isPresentArray(tail)) { - return { type: ExpressionKind.GetPath, path: { head: variable, tail } }; + return { type: GET_PATH_EXPR, path: { head: variable, tail } }; } else { - return { type: ExpressionKind.GetVar, variable }; + return { type: GET_VAR_EXPR, variable }; } } @@ -367,7 +380,7 @@ export function normalizePathHead(whole: string): Variable { if (/^this(?:\.|$)/u.test(whole)) { return { - kind: VariableKind.This, + kind: THIS_VAR, name: whole, mode: 'loose', }; @@ -375,22 +388,22 @@ export function normalizePathHead(whole: string): Variable { switch (whole[0]) { case '^': - kind = VariableKind.Free; + kind = FREE_VAR; name = whole.slice(1); break; case '@': - kind = VariableKind.Arg; + kind = ARG_VAR; name = whole.slice(1); break; case '&': - kind = VariableKind.Block; + kind = BLOCK_VAR; name = whole.slice(1); break; default: - kind = VariableKind.Local; + kind = LOCAL_VAR; name = whole; } @@ -495,7 +508,7 @@ function normalizeAttrs(attrs: BuilderAttrs): NormalizedAttrs { function normalizeAttr(attr: BuilderAttr): { expr: NormalizedAttr; trusted: boolean } { if (attr === 'splat') { - return { expr: HeadKind.Splat, trusted: false }; + return { expr: SPLAT_HEAD, trusted: false }; } else { const expr = normalizeExpression(attr); return { expr, trusted: false }; @@ -521,7 +534,7 @@ export type BuilderElement = | [string, BuilderBlock] | [string, BuilderAttrs]; -export type BuilderComment = [Builder.Comment, string]; +export type BuilderComment = [BUILDER_COMMENT, string]; export type InvocationElement = | [string] @@ -555,25 +568,13 @@ export function isBlock(input: [string, ...unknown[]]): input is BuilderBlockSta return !!match && !!match[1]; } -export enum Builder { - Literal, - Comment, - Append, - Modifier, - DynamicComponent, - Get, - Concat, - HasBlock, - HasBlockParams, -} - export type VerboseStatement = - | [Builder.Literal, string] - | [Builder.Comment, string] - | [Builder.Append, BuilderExpression, true] - | [Builder.Append, BuilderExpression] - | [Builder.Modifier, Params, Hash] - | [Builder.DynamicComponent, BuilderExpression, Hash, BuilderBlock]; + | [BUILDER_LITERAL, string] + | [BUILDER_COMMENT, string] + | [BUILDER_APPEND, BuilderExpression, true] + | [BUILDER_APPEND, BuilderExpression] + | [BUILDER_MODIFIER, Params, Hash] + | [BUILDER_DYNAMIC_COMPONENT, BuilderExpression, Hash, BuilderBlock]; export type BuilderStatement = | VerboseStatement @@ -584,54 +585,44 @@ export type BuilderStatement = export type BuilderAttr = 'splat' | BuilderExpression; export type TupleBuilderExpression = - | [Builder.Literal, string | boolean | null | undefined] - | [Builder.Get, string] - | [Builder.Get, string, string[]] - | [Builder.Concat, ...BuilderExpression[]] - | [Builder.HasBlock, string] - | [Builder.HasBlockParams, string] + | [BUILDER_LITERAL, string | boolean | null | undefined] + | [BUILDER_GET, string] + | [BUILDER_GET, string, string[]] + | [BUILDER_CONCAT, ...BuilderExpression[]] + | [BUILDER_HAS_BLOCK, string] + | [BUILDER_HAS_BLOCK_PARAMS, string] | BuilderCallExpression; type Params = BuilderParams; type Hash = Dict; -export enum ExpressionKind { - Literal = 'Literal', - Call = 'Call', - GetPath = 'GetPath', - GetVar = 'GetVar', - Concat = 'Concat', - HasBlock = 'HasBlock', - HasBlockParams = 'HasBlockParams', -} - export interface NormalizedCallExpression { - type: ExpressionKind.Call; + type: CALL_EXPR; head: NormalizedHead; params: Nullable; hash: Nullable; } export interface NormalizedPath { - type: ExpressionKind.GetPath; + type: GET_PATH_EXPR; path: Path; } export interface NormalizedVar { - type: ExpressionKind.GetVar; + type: GET_VAR_EXPR; variable: Variable; } export type NormalizedHead = NormalizedPath | NormalizedVar; export interface NormalizedConcat { - type: ExpressionKind.Concat; + type: CONCAT_EXPR; params: [NormalizedExpression, ...NormalizedExpression[]]; } export type NormalizedExpression = | { - type: ExpressionKind.Literal; + type: LITERAL_EXPR; value: null | undefined | boolean | string | number; } | NormalizedCallExpression @@ -639,11 +630,11 @@ export type NormalizedExpression = | NormalizedVar | NormalizedConcat | { - type: ExpressionKind.HasBlock; + type: HAS_BLOCK_EXPR; name: string; } | { - type: ExpressionKind.HasBlockParams; + type: HAS_BLOCK_PARAMS_EXPR; name: string; }; @@ -654,27 +645,27 @@ export function normalizeAppendExpression( if (expression === null || expression === undefined) { return { expr: { - type: ExpressionKind.Literal, + type: LITERAL_EXPR, value: expression, }, - kind: HeadKind.AppendExpr, + kind: APPEND_EXPR_HEAD, trusted: false, }; } else if (Array.isArray(expression)) { switch (expression[0]) { - case Builder.Literal: + case BUILDER_LITERAL: return { - expr: { type: ExpressionKind.Literal, value: expression[1] }, - kind: HeadKind.AppendExpr, + expr: { type: LITERAL_EXPR, value: expression[1] }, + kind: APPEND_EXPR_HEAD, trusted: false, }; - case Builder.Get: { + case BUILDER_GET: { return normalizeAppendHead(normalizePath(expression[1], expression[2]), forceTrusted); } - case Builder.Concat: { + case BUILDER_CONCAT: { const expr: NormalizedConcat = { - type: ExpressionKind.Concat, + type: CONCAT_EXPR, params: normalizeParams(expression.slice(1)) as [ NormalizedExpression, ...NormalizedExpression[], @@ -683,28 +674,28 @@ export function normalizeAppendExpression( return { expr, - kind: HeadKind.AppendExpr, + kind: APPEND_EXPR_HEAD, trusted: forceTrusted, }; } - case Builder.HasBlock: + case BUILDER_HAS_BLOCK: return { expr: { - type: ExpressionKind.HasBlock, + type: HAS_BLOCK_EXPR, name: expression[1], }, - kind: HeadKind.AppendExpr, + kind: APPEND_EXPR_HEAD, trusted: forceTrusted, }; - case Builder.HasBlockParams: + case BUILDER_HAS_BLOCK_PARAMS: return { expr: { - type: ExpressionKind.HasBlockParams, + type: HAS_BLOCK_PARAMS_EXPR, name: expression[1], }, - kind: HeadKind.AppendExpr, + kind: APPEND_EXPR_HEAD, trusted: forceTrusted, }; @@ -712,7 +703,7 @@ export function normalizeAppendExpression( if (isBuilderCallExpression(expression)) { return { expr: normalizeCallExpression(expression), - kind: HeadKind.AppendExpr, + kind: APPEND_EXPR_HEAD, trusted: forceTrusted, }; } else { @@ -733,8 +724,8 @@ export function normalizeAppendExpression( case 'boolean': case 'number': return { - expr: { type: ExpressionKind.Literal, value: expression }, - kind: HeadKind.AppendExpr, + expr: { type: LITERAL_EXPR, value: expression }, + kind: APPEND_EXPR_HEAD, trusted: true, }; @@ -749,20 +740,20 @@ export function normalizeAppendExpression( export function normalizeExpression(expression: BuilderExpression): NormalizedExpression { if (expression === null || expression === undefined) { return { - type: ExpressionKind.Literal, + type: LITERAL_EXPR, value: expression, }; } else if (Array.isArray(expression)) { switch (expression[0]) { - case Builder.Literal: - return { type: ExpressionKind.Literal, value: expression[1] }; + case BUILDER_LITERAL: + return { type: LITERAL_EXPR, value: expression[1] }; - case Builder.Get: { + case BUILDER_GET: { return normalizePath(expression[1], expression[2]); } - case Builder.Concat: { + case BUILDER_CONCAT: { const expr: NormalizedConcat = { - type: ExpressionKind.Concat, + type: CONCAT_EXPR, params: normalizeParams(expression.slice(1)) as [ NormalizedExpression, ...NormalizedExpression[], @@ -772,15 +763,15 @@ export function normalizeExpression(expression: BuilderExpression): NormalizedEx return expr; } - case Builder.HasBlock: + case BUILDER_HAS_BLOCK: return { - type: ExpressionKind.HasBlock, + type: HAS_BLOCK_EXPR, name: expression[1], }; - case Builder.HasBlockParams: + case BUILDER_HAS_BLOCK_PARAMS: return { - type: ExpressionKind.HasBlockParams, + type: HAS_BLOCK_PARAMS_EXPR, name: expression[1], }; @@ -804,7 +795,7 @@ export function normalizeExpression(expression: BuilderExpression): NormalizedEx } case 'boolean': case 'number': - return { type: ExpressionKind.Literal, value: expression }; + return { type: LITERAL_EXPR, value: expression }; default: throw assertNever(expression); @@ -814,11 +805,11 @@ export function normalizeExpression(expression: BuilderExpression): NormalizedEx } } -// | [Builder.Get, string] -// | [Builder.Get, string, string[]] -// | [Builder.Concat, Params] -// | [Builder.HasBlock, string] -// | [Builder.HasBlockParams, string] +// | [GET, string] +// | [GET, string, string[]] +// | [CONCAT, Params] +// | [HAS_BLOCK, string] +// | [HAS_BLOCK_PARAMS, string] export type BuilderExpression = | TupleBuilderExpression @@ -837,7 +828,7 @@ export function isBuilderExpression( export function isLiteral( expr: BuilderExpression | BuilderCallExpression -): expr is [Builder.Literal, string | boolean | undefined] { +): expr is [BUILDER_LITERAL, string | boolean | undefined] { return Array.isArray(expr) && expr[0] === 'literal'; } @@ -852,11 +843,11 @@ export function statementIsExpression( if (typeof name === 'number') { switch (name) { - case Builder.Literal: - case Builder.Get: - case Builder.Concat: - case Builder.HasBlock: - case Builder.HasBlockParams: + case BUILDER_LITERAL: + case BUILDER_GET: + case BUILDER_CONCAT: + case BUILDER_HAS_BLOCK: + case BUILDER_HAS_BLOCK_PARAMS: return true; default: return false; @@ -895,7 +886,7 @@ export function normalizeCallExpression(expr: BuilderCallExpression): Normalized switch (expr.length) { case 1: return { - type: ExpressionKind.Call, + type: CALL_EXPR, head: normalizeCallHead(expr[0]), params: null, hash: null, @@ -903,14 +894,14 @@ export function normalizeCallExpression(expr: BuilderCallExpression): Normalized case 2: { if (Array.isArray(expr[1])) { return { - type: ExpressionKind.Call, + type: CALL_EXPR, head: normalizeCallHead(expr[0]), params: normalizeParams(expr[1]), hash: null, }; } else { return { - type: ExpressionKind.Call, + type: CALL_EXPR, head: normalizeCallHead(expr[0]), params: null, hash: normalizeHash(expr[1]), @@ -920,7 +911,7 @@ export function normalizeCallExpression(expr: BuilderCallExpression): Normalized case 3: return { - type: ExpressionKind.Call, + type: CALL_EXPR, head: normalizeCallHead(expr[0]), params: normalizeParams(expr[1]), hash: normalizeHash(expr[2]), diff --git a/packages/@glimmer/compiler/lib/builder/builder.ts b/packages/@glimmer/compiler/lib/builder/builder.ts index 03bb147315..ad30bb41b1 100644 --- a/packages/@glimmer/compiler/lib/builder/builder.ts +++ b/packages/@glimmer/compiler/lib/builder/builder.ts @@ -1,3 +1,4 @@ +import type { VariableKind } from '@glimmer/constants'; import type { AttrNamespace, Dict, @@ -7,8 +8,38 @@ import type { PresentArray, WireFormat, } from '@glimmer/interfaces'; +import { + APPEND_EXPR_HEAD, + APPEND_PATH_HEAD, + ARG_VAR, + BLOCK_HEAD, + BLOCK_VAR, + BUILDER_COMMENT, + BUILDER_LITERAL, + CALL_EXPR, + CALL_HEAD, + COMMENT_HEAD, + CONCAT_EXPR, + DYNAMIC_COMPONENT_HEAD, + ELEMENT_HEAD, + FREE_VAR, + GET_PATH_EXPR, + GET_VAR_EXPR, + HAS_BLOCK_EXPR, + HAS_BLOCK_PARAMS_EXPR, + KEYWORD_HEAD, + LITERAL_EXPR, + LITERAL_HEAD, + LOCAL_VAR, + MODIFIER_HEAD, + NS_XLINK, + NS_XML, + NS_XMLNS, + SPLAT_HEAD, + THIS_VAR, +} from '@glimmer/constants'; import { assert, exhausted, expect, isPresentArray } from '@glimmer/debug-util'; -import { assertNever, dict, NS_XLINK, NS_XML, NS_XMLNS, values } from '@glimmer/util'; +import { assertNever, dict, values } from '@glimmer/util'; import { SexpOpcodes as Op, VariableResolutionContext } from '@glimmer/wire-format'; import type { @@ -29,13 +60,7 @@ import type { Variable, } from './builder-interface'; -import { - Builder, - ExpressionKind, - HeadKind, - normalizeStatement, - VariableKind, -} from './builder-interface'; +import { normalizeStatement } from './builder-interface'; interface Symbols { top: ProgramSymbols; @@ -206,7 +231,7 @@ export function buildStatement( symbols: Symbols = new ProgramSymbols() ): WireFormat.Statement[] { switch (normalized.kind) { - case HeadKind.AppendPath: { + case APPEND_PATH_HEAD: { return [ [ normalized.trusted ? Op.TrustingAppend : Op.Append, @@ -215,7 +240,7 @@ export function buildStatement( ]; } - case HeadKind.AppendExpr: { + case APPEND_EXPR_HEAD: { return [ [ normalized.trusted ? Op.TrustingAppend : Op.Append, @@ -228,7 +253,7 @@ export function buildStatement( ]; } - case HeadKind.Call: { + case CALL_HEAD: { let { head: path, params, hash, trusted } = normalized; let builtParams: Nullable = params ? buildParams(params, symbols) @@ -247,15 +272,15 @@ export function buildStatement( ]; } - case HeadKind.Literal: { + case LITERAL_HEAD: { return [[Op.Append, normalized.value]]; } - case HeadKind.Comment: { + case COMMENT_HEAD: { return [[Op.Comment, normalized.value]]; } - case HeadKind.Block: { + case BLOCK_HEAD: { let blocks = buildBlocks(normalized.blocks, normalized.blockParams, symbols); let hash = buildHash(normalized.hash, symbols); let params = buildParams(normalized.params, symbols); @@ -268,17 +293,17 @@ export function buildStatement( return [[Op.Block, path, params, hash, blocks]]; } - case HeadKind.Keyword: { + case KEYWORD_HEAD: { return [buildKeyword(normalized, symbols)]; } - case HeadKind.Element: + case ELEMENT_HEAD: return buildElement(normalized, symbols); - case HeadKind.Modifier: + case MODIFIER_HEAD: throw unimpl('modifier'); - case HeadKind.DynamicComponent: + case DYNAMIC_COMPONENT_HEAD: throw unimpl('dynamic component'); default: @@ -289,13 +314,13 @@ export function buildStatement( export function s( arr: TemplateStringsArray, ...interpolated: unknown[] -): [Builder.Literal, string] { +): [BUILDER_LITERAL, string] { let result = arr.reduce( (result, string, i) => result + `${string}${interpolated[i] ? String(interpolated[i]) : ''}`, '' ); - return [Builder.Literal, result]; + return [BUILDER_LITERAL, result]; } export function c(arr: TemplateStringsArray, ...interpolated: unknown[]): BuilderComment { @@ -304,7 +329,7 @@ export function c(arr: TemplateStringsArray, ...interpolated: unknown[]): Builde '' ); - return [Builder.Comment, result]; + return [BUILDER_COMMENT, result]; } export function unicode(charCode: string): string { @@ -376,7 +401,7 @@ function buildElement( function hasSplat(attrs: Nullable): boolean { if (attrs === null) return false; - return Object.keys(attrs).some((a) => attrs[a] === HeadKind.Splat); + return Object.keys(attrs).some((a) => attrs[a] === SPLAT_HEAD); } export function buildAngleInvocation( @@ -413,7 +438,7 @@ export function buildElementParams( let values: WireFormat.Expression[] = []; for (const [key, value] of Object.entries(attrs)) { - if (value === HeadKind.Splat) { + if (value === SPLAT_HEAD) { params.push([Op.AttrSplat, symbols.block('&attrs')]); } else if (key[0] === '@') { keys.push(key); @@ -466,7 +491,7 @@ export function buildAttributeValue( symbols: Symbols ): WireFormat.Attribute[] { switch (value.type) { - case ExpressionKind.Literal: { + case LITERAL_EXPR: { let val = value.value; if (val === false) { @@ -519,19 +544,19 @@ export function buildExpression( symbols: Symbols ): WireFormat.Expression { switch (expr.type) { - case ExpressionKind.GetPath: { + case GET_PATH_EXPR: { return buildGetPath(expr, symbols); } - case ExpressionKind.GetVar: { + case GET_VAR_EXPR: { return buildVar(expr.variable, varContext(context, true), symbols); } - case ExpressionKind.Concat: { + case CONCAT_EXPR: { return [Op.Concat, buildConcat(expr.params, symbols)]; } - case ExpressionKind.Call: { + case CALL_EXPR: { let builtParams = buildParams(expr.params, symbols); let builtHash = buildHash(expr.hash, symbols); let builtExpr = buildCallHead( @@ -543,29 +568,29 @@ export function buildExpression( return [Op.Call, builtExpr, builtParams, builtHash]; } - case ExpressionKind.HasBlock: { + case HAS_BLOCK_EXPR: { return [ Op.HasBlock, buildVar( - { kind: VariableKind.Block, name: expr.name, mode: 'loose' }, + { kind: BLOCK_VAR, name: expr.name, mode: 'loose' }, VariableResolutionContext.Strict, symbols ), ]; } - case ExpressionKind.HasBlockParams: { + case HAS_BLOCK_PARAMS_EXPR: { return [ Op.HasBlockParams, buildVar( - { kind: VariableKind.Block, name: expr.name, mode: 'loose' }, + { kind: BLOCK_VAR, name: expr.name, mode: 'loose' }, VariableResolutionContext.Strict, symbols ), ]; } - case ExpressionKind.Literal: { + case LITERAL_EXPR: { if (expr.value === undefined) { return [Op.Undefined]; } else { @@ -583,7 +608,7 @@ export function buildCallHead( context: VarResolution, symbols: Symbols ): Expressions.GetVar | Expressions.GetPath { - if (callHead.type === ExpressionKind.GetVar) { + if (callHead.type === GET_VAR_EXPR) { return buildVar(callHead.variable, context, symbols); } else { return buildGetPath(callHead, symbols); @@ -625,7 +650,7 @@ export function buildVar( let op: Expressions.GetPath[0] | Expressions.GetVar[0] = Op.GetSymbol; let sym: number; switch (head.kind) { - case VariableKind.Free: + case FREE_VAR: if (context === 'Strict') { op = Op.GetStrictKeyword; } else if (context === 'AppendBare') { @@ -660,19 +685,15 @@ export function buildVar( } } -function getSymbolForVar( - kind: Exclude, - symbols: Symbols, - name: string -) { +function getSymbolForVar(kind: Exclude, symbols: Symbols, name: string) { switch (kind) { - case VariableKind.Arg: + case ARG_VAR: return symbols.arg(name); - case VariableKind.Block: + case BLOCK_VAR: return symbols.block(name); - case VariableKind.Local: + case LOCAL_VAR: return symbols.local(name); - case VariableKind.This: + case THIS_VAR: return symbols.this(); default: return exhausted(kind); diff --git a/packages/@glimmer/compiler/lib/compiler.ts b/packages/@glimmer/compiler/lib/compiler.ts index 28238f447b..6e67e40cf7 100644 --- a/packages/@glimmer/compiler/lib/compiler.ts +++ b/packages/@glimmer/compiler/lib/compiler.ts @@ -9,7 +9,7 @@ import type { PrecompileOptionsWithLexicalScope, TemplateIdFn, } from '@glimmer/syntax'; -import { LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import { normalize, src } from '@glimmer/syntax'; import { LOCAL_LOGGER } from '@glimmer/util'; @@ -84,8 +84,8 @@ export function precompileJSON( return pass2(pass2In); }); - if (LOCAL_SHOULD_LOG) { - LOCAL_LOGGER.log(`Template ->`, block); + if (LOCAL_TRACE_LOGGING) { + LOCAL_LOGGER.debug(`Template ->`, block); } if (block.isOk) { diff --git a/packages/@glimmer/compiler/lib/passes/1-normalization/index.ts b/packages/@glimmer/compiler/lib/passes/1-normalization/index.ts index d6558d3b7d..117f216b85 100644 --- a/packages/@glimmer/compiler/lib/passes/1-normalization/index.ts +++ b/packages/@glimmer/compiler/lib/passes/1-normalization/index.ts @@ -1,5 +1,5 @@ import type { ASTv2, src } from '@glimmer/syntax'; -import { LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import { LOCAL_LOGGER } from '@glimmer/util'; import type { Result } from '../../shared/result'; @@ -55,20 +55,20 @@ export default function normalize( // create a new context for the normalization pass let state = new NormalizationState(root.table, isStrict); - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { LOCAL_LOGGER.groupCollapsed(`pass0: visiting`); - LOCAL_LOGGER.log('symbols', root.table); - LOCAL_LOGGER.log('source', source); + LOCAL_LOGGER.debug('symbols', root.table); + LOCAL_LOGGER.debug('source', source); LOCAL_LOGGER.groupEnd(); } let body = VISIT_STMTS.visitList(root.body, state); - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { if (body.isOk) { - LOCAL_LOGGER.log('-> pass0: out', body.value); + LOCAL_LOGGER.debug('-> pass0: out', body.value); } else { - LOCAL_LOGGER.log('-> pass0: error', body.reason); + LOCAL_LOGGER.debug('-> pass0: error', body.reason); } } diff --git a/packages/@glimmer/compiler/lib/passes/1-normalization/visitors/constants.ts b/packages/@glimmer/compiler/lib/passes/1-normalization/visitors/constants.ts new file mode 100644 index 0000000000..31408e936d --- /dev/null +++ b/packages/@glimmer/compiler/lib/passes/1-normalization/visitors/constants.ts @@ -0,0 +1,23 @@ +/// ResolutionType /// + +export type VALUE_RESOLUTION = 'value'; +export const VALUE_RESOLUTION: VALUE_RESOLUTION = 'value'; + +export type COMPONENT_RESOLUTION = 'component'; +export const COMPONENT_RESOLUTION: COMPONENT_RESOLUTION = 'component'; + +export type HELPER_RESOLUTION = 'helper'; +export const HELPER_RESOLUTION: HELPER_RESOLUTION = 'helper'; + +export type MODIFIER_RESOLUTION = 'modifier'; +export const MODIFIER_RESOLUTION: MODIFIER_RESOLUTION = 'modifier'; + +export type COMPONENT_OR_HELPER_RESOLUTION = 'component or helper'; +export const COMPONENT_OR_HELPER_RESOLUTION: COMPONENT_OR_HELPER_RESOLUTION = 'component or helper'; + +export type ResolutionType = + | VALUE_RESOLUTION + | COMPONENT_RESOLUTION + | HELPER_RESOLUTION + | MODIFIER_RESOLUTION + | COMPONENT_OR_HELPER_RESOLUTION; diff --git a/packages/@glimmer/compiler/lib/passes/1-normalization/visitors/strict-mode.ts b/packages/@glimmer/compiler/lib/passes/1-normalization/visitors/strict-mode.ts index 433e905711..ab9787f200 100644 --- a/packages/@glimmer/compiler/lib/passes/1-normalization/visitors/strict-mode.ts +++ b/packages/@glimmer/compiler/lib/passes/1-normalization/visitors/strict-mode.ts @@ -4,16 +4,16 @@ import { CurriedTypes } from '@glimmer/vm'; import type { Result } from '../../../shared/result'; import type * as mir from '../../2-encoding/mir'; +import type { ResolutionType } from './constants'; import { Err, Ok } from '../../../shared/result'; - -enum ResolutionType { - Value = 'value', - Component = 'component', - Helper = 'helper', - Modifier = 'modifier', - ComponentOrHelper = 'component or helper', -} +import { + COMPONENT_OR_HELPER_RESOLUTION, + COMPONENT_RESOLUTION, + HELPER_RESOLUTION, + MODIFIER_RESOLUTION, + VALUE_RESOLUTION, +} from './constants'; export default class StrictModeValidationPass { // This is done at the end of all the keyword normalizations @@ -140,7 +140,7 @@ export default class StrictModeValidationPass { return this.InterpolateExpression(expression, span, resolution); case 'CallExpression': - return this.CallExpression(expression, span, resolution ?? ResolutionType.Helper); + return this.CallExpression(expression, span, resolution ?? HELPER_RESOLUTION); case 'Not': return this.Expression(expression.value, span, resolution); @@ -188,7 +188,7 @@ export default class StrictModeValidationPass { NamedArgument(arg: mir.NamedArgument): Result { if (arg.value.type === 'CallExpression') { - return this.Expression(arg.value, arg, ResolutionType.Helper); + return this.Expression(arg.value, arg, HELPER_RESOLUTION); } else { return this.Expression(arg.value, arg); } @@ -219,14 +219,14 @@ export default class StrictModeValidationPass { DynamicAttr(attr: mir.DynamicAttr): Result { if (attr.value.type === 'CallExpression') { - return this.Expression(attr.value, attr, ResolutionType.Helper); + return this.Expression(attr.value, attr, HELPER_RESOLUTION); } else { return this.Expression(attr.value, attr); } } Modifier(modifier: mir.Modifier): Result { - return this.Expression(modifier.callee, modifier, ResolutionType.Modifier).andThen(() => + return this.Expression(modifier.callee, modifier, MODIFIER_RESOLUTION).andThen(() => this.Args(modifier.args) ); } @@ -250,14 +250,14 @@ export default class StrictModeValidationPass { AppendTextNode(statement: mir.AppendTextNode): Result { if (statement.text.type === 'CallExpression') { - return this.Expression(statement.text, statement, ResolutionType.ComponentOrHelper); + return this.Expression(statement.text, statement, COMPONENT_OR_HELPER_RESOLUTION); } else { return this.Expression(statement.text, statement); } } Component(statement: mir.Component): Result { - return this.Expression(statement.tag, statement, ResolutionType.Component) + return this.Expression(statement.tag, statement, COMPONENT_RESOLUTION) .andThen(() => this.ElementParameters(statement.params)) .andThen(() => this.NamedArguments(statement.args)) .andThen(() => this.NamedBlocks(statement.blocks)); @@ -268,7 +268,7 @@ export default class StrictModeValidationPass { } InvokeBlock(statement: mir.InvokeBlock): Result { - return this.Expression(statement.head, statement.head, ResolutionType.Component) + return this.Expression(statement.head, statement.head, COMPONENT_RESOLUTION) .andThen(() => this.Args(statement.args)) .andThen(() => this.NamedBlocks(statement.blocks)); } @@ -313,7 +313,7 @@ export default class StrictModeValidationPass { } InvokeComponent(statement: mir.InvokeComponent): Result { - return this.Expression(statement.definition, statement, ResolutionType.Component) + return this.Expression(statement.definition, statement, COMPONENT_RESOLUTION) .andThen(() => this.Args(statement.args)) .andThen(() => { if (statement.blocks) { @@ -364,11 +364,11 @@ export default class StrictModeValidationPass { let resolution: ResolutionType; if (expression.curriedType === CurriedTypes.Component) { - resolution = ResolutionType.Component; + resolution = COMPONENT_RESOLUTION; } else if (expression.curriedType === CurriedTypes.Helper) { - resolution = ResolutionType.Helper; + resolution = HELPER_RESOLUTION; } else { - resolution = ResolutionType.Modifier; + resolution = MODIFIER_RESOLUTION; } return this.Expression(expression.definition, expression, resolution).andThen(() => @@ -380,7 +380,11 @@ export default class StrictModeValidationPass { return this.Positional(expression.positional, expression); } - errorFor(name: string, span: HasSourceSpan, type = ResolutionType.Value): Result { + errorFor( + name: string, + span: HasSourceSpan, + type: ResolutionType = VALUE_RESOLUTION + ): Result { return Err( generateSyntaxError( `Attempted to resolve a ${type} in a strict mode template, but that value was not in scope: ${name}`, diff --git a/packages/@glimmer/compiler/lib/passes/2-encoding/content.ts b/packages/@glimmer/compiler/lib/passes/2-encoding/content.ts index 4cacc0bb74..c8ca14246b 100644 --- a/packages/@glimmer/compiler/lib/passes/2-encoding/content.ts +++ b/packages/@glimmer/compiler/lib/passes/2-encoding/content.ts @@ -10,7 +10,7 @@ import type { WireFormat, } from '@glimmer/interfaces'; import { exhausted } from '@glimmer/debug-util'; -import { LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import { LOCAL_LOGGER } from '@glimmer/util'; import { SexpOpcodes } from '@glimmer/wire-format'; @@ -46,8 +46,8 @@ export class ContentEncoder { } content(stmt: mir.Statement): WireFormat.Statement | WireStatements { - if (LOCAL_SHOULD_LOG) { - LOCAL_LOGGER.log(`encoding`, stmt); + if (LOCAL_TRACE_LOGGING) { + LOCAL_LOGGER.debug(`encoding`, stmt); } return this.visitContent(stmt); diff --git a/packages/@glimmer/compiler/lib/passes/2-encoding/index.ts b/packages/@glimmer/compiler/lib/passes/2-encoding/index.ts index 585a28f8ca..9896df1d1b 100644 --- a/packages/@glimmer/compiler/lib/passes/2-encoding/index.ts +++ b/packages/@glimmer/compiler/lib/passes/2-encoding/index.ts @@ -1,5 +1,5 @@ import type { WireFormat } from '@glimmer/interfaces'; -import { LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import { LOCAL_LOGGER } from '@glimmer/util'; import type * as mir from './mir'; @@ -17,9 +17,9 @@ export function visit(template: mir.Template): WireFormat.SerializedTemplateBloc scope.upvars, ]; - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { let debug = new WireFormatDebugger(block); - LOCAL_LOGGER.log( + LOCAL_LOGGER.debug( `-> `, statements.map((s) => debug.formatOpcode(s)) ); diff --git a/packages/@glimmer/compiler/package.json b/packages/@glimmer/compiler/package.json index be44f9b15d..b0b9f4520c 100644 --- a/packages/@glimmer/compiler/package.json +++ b/packages/@glimmer/compiler/package.json @@ -46,12 +46,13 @@ }, "devDependencies": { "@glimmer-workspace/build-support": "workspace:*", + "@glimmer/constants": "workspace:*", "@glimmer/debug-util": "workspace:*", "@glimmer/local-debug-flags": "workspace:*", "@types/node": "^20.9.4", "eslint": "^8.52.0", "publint": "^0.2.5", - "rollup": "^4.5.1", + "rollup": "^4.24.3", "typescript": "*" }, "engines": { diff --git a/packages/@glimmer/compiler/test/compiler-test.ts b/packages/@glimmer/compiler/test/compiler-test.ts index 839fa80ce1..555fabb2b2 100644 --- a/packages/@glimmer/compiler/test/compiler-test.ts +++ b/packages/@glimmer/compiler/test/compiler-test.ts @@ -7,7 +7,6 @@ import type { SerializedTemplateWithLazyBlock, } from '@glimmer/interfaces'; import { - Builder, buildStatements, c, NEWLINE, @@ -17,6 +16,7 @@ import { unicode, WireFormatDebugger, } from '@glimmer/compiler'; +import { BUILDER_APPEND, BUILDER_CONCAT } from '@glimmer/constants'; import { assign, strip } from '@glimmer/util'; QUnit.module('@glimmer/compiler - compiling source to wire format'); @@ -50,9 +50,6 @@ function test(desc: string, template: string, ...expectedStatements: BuilderStat }); } -const Append = Builder.Append; -const Concat = Builder.Concat; - QUnit.test( '@arguments are on regular non-component/regular HTML nodes throws syntax error', (assert) => { @@ -71,8 +68,8 @@ test('HTML text content', 'content', s`content`); test('Text curlies', '
{{title}}{{title}}
', [ '
', [ - [Append, '^title'], - ['', [[Append, '^title']]], + [BUILDER_APPEND, '^title'], + ['', [[BUILDER_APPEND, '^title']]], ], ]); @@ -190,7 +187,12 @@ test( "", [ '', - [['', { 'data-src': [Concat, s`extra-`, '^someDynamicBits', s`-here`] }]], + [ + [ + '', + { 'data-src': [BUILDER_CONCAT, s`extra-`, '^someDynamicBits', s`-here`] }, + ], + ], ] ); @@ -223,7 +225,7 @@ test('empty attributes', `
content
`, ['
', { class: s`` } test('helpers in string attributes', `linky`, [ '', - { href: [Concat, s`http://`, ['(^testing)', [123]], s`/index.html`] }, + { href: [BUILDER_CONCAT, s`http://`, ['(^testing)', [123]], s`/index.html`] }, [s`linky`], ]); @@ -231,14 +233,14 @@ test(`boolean attribute 'disabled'`, '', ['', { disabled: test(`string quoted attributes`, ``, [ '', - { disabled: [Concat, '^isDisabled'] }, + { disabled: [BUILDER_CONCAT, '^isDisabled'] }, ]); test(`unquoted attributes`, ``, ['', { src: '^src' }]); test(`dynamic attr followed by static attr`, `
`, [ '
', - { foo: [Concat, '^funstuff'], name: s`Alice` }, + { foo: [BUILDER_CONCAT, '^funstuff'], name: s`Alice` }, ]); test( @@ -329,7 +331,7 @@ test( [ '', { 'xmlns:xlink': s`http://www.w3.org/1999/xlink` }, - [['', { 'xlink:href': [Concat, '^iconLink'] }]], + [['', { 'xlink:href': [BUILDER_CONCAT, '^iconLink'] }]], ] ); @@ -389,19 +391,22 @@ test('whitespace', `Hello {{ foo }} `, s`Hello `, '^foo', s` `); test('double curlies', `
{{title}}
`, ['
', ['^title']]); -test('triple curlies', `
{{{title}}}
`, ['
', [[Append, '^title', true]]]); +test('triple curlies', `
{{{title}}}
`, ['
', [[BUILDER_APPEND, '^title', true]]]); test( 'triple curly helpers', `{{{unescaped "Yolo"}}} {{escaped "Yolo"}}`, - [Append, ['(^unescaped)', [s`Yolo`]], true], + [BUILDER_APPEND, ['(^unescaped)', [s`Yolo`]], true], s` `, - [Append, ['(^escaped)', [s`Yolo`]]] + [BUILDER_APPEND, ['(^escaped)', [s`Yolo`]]] ); -test('top level triple curlies', `{{{title}}}`, [Append, '^title', true]); +test('top level triple curlies', `{{{title}}}`, [BUILDER_APPEND, '^title', true]); -test('top level table', `{{{title}}}
`, ['', [[Append, '^title', true]]]); +test('top level table', `
{{{title}}}
`, [ + '', + [[BUILDER_APPEND, '^title', true]], +]); test( 'X-TREME nesting', @@ -440,7 +445,7 @@ test( test('simple helpers', `
{{testing title}}
`, [ '
', - [[Append, ['(^testing)', ['^title']]]], + [[BUILDER_APPEND, ['(^testing)', ['^title']]]], ]); test('constant negative numbers', `
{{testing -123321}}
`, [ @@ -509,7 +514,7 @@ test( test('Null curly in attributes', `
hello
`, [ '
', - { class: [Concat, s`foo `, null] }, + { class: [BUILDER_CONCAT, s`foo `, null] }, [s`hello`], ]); @@ -548,13 +553,13 @@ test('hash arguments', `
{{testing first="one" second="two"}}
`, [ test('params in concat attribute position', `linky`, [ '', - { href: [Concat, ['(^testing)', ['^url']]] }, + { href: [BUILDER_CONCAT, ['(^testing)', ['^url']]] }, [s`linky`], ]); test('named args in concat attribute position', `linky`, [ '', - { href: [Concat, ['(^testing)', { path: '^url' }]] }, + { href: [BUILDER_CONCAT, ['(^testing)', { path: '^url' }]] }, [s`linky`], ]); @@ -565,7 +570,7 @@ test( '', { href: [ - Concat, + BUILDER_CONCAT, s`http://`, '^foo', s`/`, diff --git a/packages/@glimmer/compiler/test/package.json b/packages/@glimmer/compiler/test/package.json index 7744fce0a0..5d18a600f4 100644 --- a/packages/@glimmer/compiler/test/package.json +++ b/packages/@glimmer/compiler/test/package.json @@ -6,5 +6,8 @@ "@glimmer/interfaces": "workspace:*", "@glimmer/syntax": "workspace:*", "@glimmer/util": "workspace:*" + }, + "devDependencies": { + "@glimmer/constants": "workspace:*" } } diff --git a/packages/@glimmer/constants/.npmignore b/packages/@glimmer/constants/.npmignore new file mode 100644 index 0000000000..8a585dcea7 --- /dev/null +++ b/packages/@glimmer/constants/.npmignore @@ -0,0 +1,2 @@ +test/ +index.ts diff --git a/packages/@glimmer/constants/index.ts b/packages/@glimmer/constants/index.ts new file mode 100644 index 0000000000..9e0b9b3ef0 --- /dev/null +++ b/packages/@glimmer/constants/index.ts @@ -0,0 +1,5 @@ +export * from './lib/builder-constants'; +export * from './lib/dom'; +export * from './lib/immediate'; +export * from './lib/syscall-ops'; +export * from './lib/vm-ops'; diff --git a/packages/@glimmer/constants/lib/builder-constants.ts b/packages/@glimmer/constants/lib/builder-constants.ts new file mode 100644 index 0000000000..ea2caaa8cf --- /dev/null +++ b/packages/@glimmer/constants/lib/builder-constants.ts @@ -0,0 +1,127 @@ +/// Builder /// + +export type BUILDER_LITERAL = 0; +export const BUILDER_LITERAL: BUILDER_LITERAL = 0; + +export type BUILDER_COMMENT = 1; +export const BUILDER_COMMENT: BUILDER_COMMENT = 1; + +export type BUILDER_APPEND = 2; +export const BUILDER_APPEND: BUILDER_APPEND = 2; + +export type BUILDER_MODIFIER = 3; +export const BUILDER_MODIFIER: BUILDER_MODIFIER = 3; + +export type BUILDER_DYNAMIC_COMPONENT = 4; +export const BUILDER_DYNAMIC_COMPONENT: BUILDER_DYNAMIC_COMPONENT = 4; + +export type BUILDER_GET = 5; +export const BUILDER_GET: BUILDER_GET = 5; + +export type BUILDER_CONCAT = 6; +export const BUILDER_CONCAT: BUILDER_CONCAT = 6; + +export type BUILDER_HAS_BLOCK = 7; +export const BUILDER_HAS_BLOCK: BUILDER_HAS_BLOCK = 7; + +export type BUILDER_HAS_BLOCK_PARAMS = 8; +export const BUILDER_HAS_BLOCK_PARAMS: BUILDER_HAS_BLOCK_PARAMS = 8; + +/// HeadKind /// + +export type BLOCK_HEAD = 'Block'; +export const BLOCK_HEAD: BLOCK_HEAD = 'Block'; + +export type CALL_HEAD = 'Call'; +export const CALL_HEAD: CALL_HEAD = 'Call'; + +export type ELEMENT_HEAD = 'Element'; +export const ELEMENT_HEAD: ELEMENT_HEAD = 'Element'; + +export type APPEND_PATH_HEAD = 'AppendPath'; +export const APPEND_PATH_HEAD: APPEND_PATH_HEAD = 'AppendPath'; + +export type APPEND_EXPR_HEAD = 'AppendExpr'; +export const APPEND_EXPR_HEAD: APPEND_EXPR_HEAD = 'AppendExpr'; + +export type LITERAL_HEAD = 'Literal'; +export const LITERAL_HEAD: LITERAL_HEAD = 'Literal'; + +export type MODIFIER_HEAD = 'Modifier'; +export const MODIFIER_HEAD: MODIFIER_HEAD = 'Modifier'; + +export type DYNAMIC_COMPONENT_HEAD = 'DynamicComponent'; +export const DYNAMIC_COMPONENT_HEAD: DYNAMIC_COMPONENT_HEAD = 'DynamicComponent'; + +export type COMMENT_HEAD = 'Comment'; +export const COMMENT_HEAD: COMMENT_HEAD = 'Comment'; + +export type SPLAT_HEAD = 'Splat'; +export const SPLAT_HEAD: SPLAT_HEAD = 'Splat'; + +export type KEYWORD_HEAD = 'Keyword'; +export const KEYWORD_HEAD: KEYWORD_HEAD = 'Keyword'; + +export type HeadKind = + | BLOCK_HEAD + | CALL_HEAD + | ELEMENT_HEAD + | APPEND_PATH_HEAD + | APPEND_EXPR_HEAD + | LITERAL_HEAD + | MODIFIER_HEAD + | DYNAMIC_COMPONENT_HEAD + | COMMENT_HEAD + | SPLAT_HEAD + | KEYWORD_HEAD; + +/// VariableKind /// + +export type LOCAL_VAR = 'Local'; +export const LOCAL_VAR: LOCAL_VAR = 'Local'; + +export type FREE_VAR = 'Free'; +export const FREE_VAR: FREE_VAR = 'Free'; + +export type ARG_VAR = 'Arg'; +export const ARG_VAR: ARG_VAR = 'Arg'; + +export type BLOCK_VAR = 'Block'; +export const BLOCK_VAR: BLOCK_VAR = 'Block'; + +export type THIS_VAR = 'This'; +export const THIS_VAR: THIS_VAR = 'This'; + +export type VariableKind = LOCAL_VAR | FREE_VAR | ARG_VAR | BLOCK_VAR | THIS_VAR; + +/// ExpressionKind /// + +export type LITERAL_EXPR = 'Literal'; +export const LITERAL_EXPR: LITERAL_EXPR = 'Literal'; + +export type CALL_EXPR = 'Call'; +export const CALL_EXPR: CALL_EXPR = 'Call'; + +export type GET_PATH_EXPR = 'GetPath'; +export const GET_PATH_EXPR: GET_PATH_EXPR = 'GetPath'; + +export type GET_VAR_EXPR = 'GetVar'; +export const GET_VAR_EXPR: GET_VAR_EXPR = 'GetVar'; + +export type CONCAT_EXPR = 'Concat'; +export const CONCAT_EXPR: CONCAT_EXPR = 'Concat'; + +export type HAS_BLOCK_EXPR = 'HasBlock'; +export const HAS_BLOCK_EXPR: HAS_BLOCK_EXPR = 'HasBlock'; + +export type HAS_BLOCK_PARAMS_EXPR = 'HasBlockParams'; +export const HAS_BLOCK_PARAMS_EXPR: HAS_BLOCK_PARAMS_EXPR = 'HasBlockParams'; + +export type ExpressionKind = + | LITERAL_EXPR + | CALL_EXPR + | GET_PATH_EXPR + | GET_VAR_EXPR + | CONCAT_EXPR + | HAS_BLOCK_EXPR + | HAS_BLOCK_PARAMS_EXPR; diff --git a/packages/@glimmer/util/lib/dom-utils.ts b/packages/@glimmer/constants/lib/dom.ts similarity index 100% rename from packages/@glimmer/util/lib/dom-utils.ts rename to packages/@glimmer/constants/lib/dom.ts diff --git a/packages/@glimmer/util/lib/immediate.ts b/packages/@glimmer/constants/lib/immediate.ts similarity index 58% rename from packages/@glimmer/util/lib/immediate.ts rename to packages/@glimmer/constants/lib/immediate.ts index 5d38c8e4f7..e45a3e9aae 100644 --- a/packages/@glimmer/util/lib/immediate.ts +++ b/packages/@glimmer/constants/lib/immediate.ts @@ -37,30 +37,28 @@ import { LOCAL_DEBUG } from '@glimmer/local-debug-flags'; strategy. */ -export enum ImmediateConstants { - MAX_SMI = 2 ** 30 - 1, - MIN_SMI = ~MAX_SMI, - SIGN_BIT = ~(2 ** 29), - MAX_INT = ~SIGN_BIT - 1, - MIN_INT = ~MAX_INT, - - FALSE_HANDLE = 0, - TRUE_HANDLE = 1, - NULL_HANDLE = 2, - UNDEFINED_HANDLE = 3, - - ENCODED_FALSE_HANDLE = FALSE_HANDLE, - ENCODED_TRUE_HANDLE = TRUE_HANDLE, - ENCODED_NULL_HANDLE = NULL_HANDLE, - ENCODED_UNDEFINED_HANDLE = UNDEFINED_HANDLE, -} +export const MAX_SMI = 2 ** 30 - 1; +export const MIN_SMI = ~MAX_SMI; +export const SIGN_BIT = ~(2 ** 29); +export const MAX_INT = ~SIGN_BIT - 1; +export const MIN_INT = ~MAX_INT; + +export const FALSE_HANDLE = 0; +export const TRUE_HANDLE = 1; +export const NULL_HANDLE = 2; +export const UNDEFINED_HANDLE = 3; + +export const ENCODED_FALSE_HANDLE = FALSE_HANDLE; +export const ENCODED_TRUE_HANDLE = TRUE_HANDLE; +export const ENCODED_NULL_HANDLE = NULL_HANDLE; +export const ENCODED_UNDEFINED_HANDLE = UNDEFINED_HANDLE; export function isHandle(value: number) { return value >= 0; } export function isNonPrimitiveHandle(value: number) { - return (value as ImmediateConstants) > ImmediateConstants.ENCODED_UNDEFINED_HANDLE; + return value > ENCODED_UNDEFINED_HANDLE; } export function constants(...values: unknown[]): unknown[] { @@ -68,43 +66,28 @@ export function constants(...values: unknown[]): unknown[] { } export function isSmallInt(value: number) { - return ( - value % 1 === 0 && - (value as ImmediateConstants) <= ImmediateConstants.MAX_INT && - (value as ImmediateConstants) >= ImmediateConstants.MIN_INT - ); + return value % 1 === 0 && value <= MAX_INT && value >= MIN_INT; } export function encodeNegative(num: number) { if (LOCAL_DEBUG) { - assert( - num % 1 === 0 && (num as ImmediateConstants) >= ImmediateConstants.MIN_INT && num < 0, - `Could not encode negative: ${num}` - ); + assert(num % 1 === 0 && num >= MIN_INT && num < 0, `Could not encode negative: ${num}`); } - return num & ImmediateConstants.SIGN_BIT; + return num & SIGN_BIT; } export function decodeNegative(num: number) { if (LOCAL_DEBUG) { - assert( - num % 1 === 0 && - num < ~ImmediateConstants.MAX_INT && - (num as ImmediateConstants) >= ImmediateConstants.MIN_SMI, - `Could not decode negative: ${num}` - ); + assert(num % 1 === 0 && num < ~MAX_INT && num >= MIN_SMI, `Could not decode negative: ${num}`); } - return num | ~ImmediateConstants.SIGN_BIT; + return num | ~SIGN_BIT; } export function encodePositive(num: number) { if (LOCAL_DEBUG) { - assert( - num % 1 === 0 && num >= 0 && (num as ImmediateConstants) <= ImmediateConstants.MAX_INT, - `Could not encode positive: ${num}` - ); + assert(num % 1 === 0 && num >= 0 && num <= MAX_INT, `Could not encode positive: ${num}`); } return ~num; @@ -112,10 +95,7 @@ export function encodePositive(num: number) { export function decodePositive(num: number) { if (LOCAL_DEBUG) { - assert( - num % 1 === 0 && num <= 0 && num >= ~ImmediateConstants.MAX_INT, - `Could not decode positive: ${num}` - ); + assert(num % 1 === 0 && num <= 0 && num >= ~MAX_INT, `Could not decode positive: ${num}`); } return ~num; @@ -123,10 +103,7 @@ export function decodePositive(num: number) { export function encodeHandle(num: number) { if (LOCAL_DEBUG) { - assert( - num % 1 === 0 && num >= 0 && (num as ImmediateConstants) <= ImmediateConstants.MAX_SMI, - `Could not encode handle: ${num}` - ); + assert(num % 1 === 0 && num >= 0 && num <= MAX_SMI, `Could not encode handle: ${num}`); } return num; @@ -134,10 +111,7 @@ export function encodeHandle(num: number) { export function decodeHandle(num: number) { if (LOCAL_DEBUG) { - assert( - num % 1 === 0 && (num as ImmediateConstants) <= ImmediateConstants.MAX_SMI && num >= 0, - `Could not decode handle: ${num}` - ); + assert(num % 1 === 0 && num <= MAX_SMI && num >= 0, `Could not decode handle: ${num}`); } return num; @@ -150,9 +124,7 @@ export function encodeImmediate(num: number) { export function decodeImmediate(num: number) { num |= 0; - return (num as ImmediateConstants) > ImmediateConstants.SIGN_BIT - ? decodePositive(num) - : decodeNegative(num); + return num > SIGN_BIT ? decodePositive(num) : decodeNegative(num); } // Warm diff --git a/packages/@glimmer/constants/lib/syscall-ops.ts b/packages/@glimmer/constants/lib/syscall-ops.ts new file mode 100644 index 0000000000..5f40816b41 --- /dev/null +++ b/packages/@glimmer/constants/lib/syscall-ops.ts @@ -0,0 +1,198 @@ +import type { + VmAppendDocumentFragment, + VmAppendHTML, + VmAppendNode, + VmAppendSafeHTML, + VmAppendText, + VmAssertSame, + VmBeginComponentTransaction, + VmBindDynamicScope, + VmBindEvalScope, + VmCaptureArgs, + VmChildScope, + VmCloseElement, + VmComment, + VmCommitComponentTransaction, + VmCompileBlock, + VmComponentAttr, + VmConcat, + VmConstant, + VmConstantReference, + VmContentType, + VmCreateComponent, + VmCurry, + VmDebugger, + VmDidCreateElement, + VmDidRenderLayout, + VmDup, + VmDynamicAttr, + VmDynamicContentType, + VmDynamicHelper, + VmDynamicModifier, + VmEnter, + VmEnterList, + VmExit, + VmExitList, + VmFetch, + VmFlushElement, + VmGetBlock, + VmGetComponentLayout, + VmGetComponentSelf, + VmGetComponentTagName, + VmGetDynamicVar, + VmGetProperty, + VmGetVariable, + VmHasBlock, + VmHasBlockParams, + VmHelper, + VmIfInline, + VmInvokeComponentLayout, + VmInvokeYield, + VmIterate, + VmJumpEq, + VmJumpIf, + VmJumpUnless, + VmLoad, + VmLog, + VmMain, + VmModifier, + VmNot, + VmOp, + VmOpenDynamicElement, + VmOpenElement, + VmPop, + VmPopArgs, + VmPopDynamicScope, + VmPopRemoteElement, + VmPopScope, + VmPopulateLayout, + VmPrepareArgs, + VmPrimitive, + VmPrimitiveReference, + VmPushArgs, + VmPushBlockScope, + VmPushComponentDefinition, + VmPushDynamicComponentInstance, + VmPushDynamicScope, + VmPushEmptyArgs, + VmPushRemoteElement, + VmPushSymbolTable, + VmPutComponentOperations, + VmRegisterComponentDestructor, + VmReifyU32, + VmResolveCurriedComponent, + VmResolveDynamicComponent, + VmRootScope, + VmSetBlock, + VmSetBlocks, + VmSetNamedVariables, + VmSetupForEval, + VmSetVariable, + VmSize, + VmSpreadBlock, + VmStaticAttr, + VmStaticComponentAttr, + VmText, + VmToBoolean, + VmVirtualRootScope, +} from '@glimmer/interfaces'; + +export const VM_HELPER_OP = 16 satisfies VmHelper; +export const VM_SET_NAMED_VARIABLES_OP = 17 satisfies VmSetNamedVariables; +export const VM_SET_BLOCKS_OP = 18 satisfies VmSetBlocks; +export const VM_SET_VARIABLE_OP = 19 satisfies VmSetVariable; +export const VM_SET_BLOCK_OP = 20 satisfies VmSetBlock; +export const VM_GET_VARIABLE_OP = 21 satisfies VmGetVariable; +export const VM_GET_PROPERTY_OP = 22 satisfies VmGetProperty; +export const VM_GET_BLOCK_OP = 23 satisfies VmGetBlock; +export const VM_SPREAD_BLOCK_OP = 24 satisfies VmSpreadBlock; +export const VM_HAS_BLOCK_OP = 25 satisfies VmHasBlock; +export const VM_HAS_BLOCK_PARAMS_OP = 26 satisfies VmHasBlockParams; +export const VM_CONCAT_OP = 27 satisfies VmConcat; +export const VM_CONSTANT_OP = 28 satisfies VmConstant; +export const VM_CONSTANT_REFERENCE_OP = 29 satisfies VmConstantReference; +export const VM_PRIMITIVE_OP = 30 satisfies VmPrimitive; +export const VM_PRIMITIVE_REFERENCE_OP = 31 satisfies VmPrimitiveReference; +export const VM_REIFY_U32_OP = 32 satisfies VmReifyU32; +export const VM_DUP_OP = 33 satisfies VmDup; +export const VM_POP_OP = 34 satisfies VmPop; +export const VM_LOAD_OP = 35 satisfies VmLoad; +export const VM_FETCH_OP = 36 satisfies VmFetch; +export const VM_ROOT_SCOPE_OP = 37 satisfies VmRootScope; +export const VM_VIRTUAL_ROOT_SCOPE_OP = 38 satisfies VmVirtualRootScope; +export const VM_CHILD_SCOPE_OP = 39 satisfies VmChildScope; +export const VM_POP_SCOPE_OP = 40 satisfies VmPopScope; +export const VM_TEXT_OP = 41 satisfies VmText; +export const VM_COMMENT_OP = 42 satisfies VmComment; +export const VM_APPEND_HTML_OP = 43 satisfies VmAppendHTML; +export const VM_APPEND_SAFE_HTML_OP = 44 satisfies VmAppendSafeHTML; +export const VM_APPEND_DOCUMENT_FRAGMENT_OP = 45 satisfies VmAppendDocumentFragment; +export const VM_APPEND_NODE_OP = 46 satisfies VmAppendNode; +export const VM_APPEND_TEXT_OP = 47 satisfies VmAppendText; +export const VM_OPEN_ELEMENT_OP = 48 satisfies VmOpenElement; +export const VM_OPEN_DYNAMIC_ELEMENT_OP = 49 satisfies VmOpenDynamicElement; +export const VM_PUSH_REMOTE_ELEMENT_OP = 50 satisfies VmPushRemoteElement; +export const VM_STATIC_ATTR_OP = 51 satisfies VmStaticAttr; +export const VM_DYNAMIC_ATTR_OP = 52 satisfies VmDynamicAttr; +export const VM_COMPONENT_ATTR_OP = 53 satisfies VmComponentAttr; +export const VM_FLUSH_ELEMENT_OP = 54 satisfies VmFlushElement; +export const VM_CLOSE_ELEMENT_OP = 55 satisfies VmCloseElement; +export const VM_POP_REMOTE_ELEMENT_OP = 56 satisfies VmPopRemoteElement; +export const VM_MODIFIER_OP = 57 satisfies VmModifier; +export const VM_BIND_DYNAMIC_SCOPE_OP = 58 satisfies VmBindDynamicScope; +export const VM_PUSH_DYNAMIC_SCOPE_OP = 59 satisfies VmPushDynamicScope; +export const VM_POP_DYNAMIC_SCOPE_OP = 60 satisfies VmPopDynamicScope; +export const VM_COMPILE_BLOCK_OP = 61 satisfies VmCompileBlock; +export const VM_PUSH_BLOCK_SCOPE_OP = 62 satisfies VmPushBlockScope; +export const VM_PUSH_SYMBOL_TABLE_OP = 63 satisfies VmPushSymbolTable; +export const VM_INVOKE_YIELD_OP = 64 satisfies VmInvokeYield; +export const VM_JUMP_IF_OP = 65 satisfies VmJumpIf; +export const VM_JUMP_UNLESS_OP = 66 satisfies VmJumpUnless; +export const VM_JUMP_EQ_OP = 67 satisfies VmJumpEq; +export const VM_ASSERT_SAME_OP = 68 satisfies VmAssertSame; +export const VM_ENTER_OP = 69 satisfies VmEnter; +export const VM_EXIT_OP = 70 satisfies VmExit; +export const VM_TO_BOOLEAN_OP = 71 satisfies VmToBoolean; +export const VM_ENTER_LIST_OP = 72 satisfies VmEnterList; +export const VM_EXIT_LIST_OP = 73 satisfies VmExitList; +export const VM_ITERATE_OP = 74 satisfies VmIterate; +export const VM_MAIN_OP = 75 satisfies VmMain; +export const VM_CONTENT_TYPE_OP = 76 satisfies VmContentType; +export const VM_CURRY_OP = 77 satisfies VmCurry; +export const VM_PUSH_COMPONENT_DEFINITION_OP = 78 satisfies VmPushComponentDefinition; +export const VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP = 79 satisfies VmPushDynamicComponentInstance; +export const VM_RESOLVE_DYNAMIC_COMPONENT_OP = 80 satisfies VmResolveDynamicComponent; +export const VM_RESOLVE_CURRIED_COMPONENT_OP = 81 satisfies VmResolveCurriedComponent; +export const VM_PUSH_ARGS_OP = 82 satisfies VmPushArgs; +export const VM_PUSH_EMPTY_ARGS_OP = 83 satisfies VmPushEmptyArgs; +export const VM_POP_ARGS_OP = 84 satisfies VmPopArgs; +export const VM_PREPARE_ARGS_OP = 85 satisfies VmPrepareArgs; +export const VM_CAPTURE_ARGS_OP = 86 satisfies VmCaptureArgs; +export const VM_CREATE_COMPONENT_OP = 87 satisfies VmCreateComponent; +export const VM_REGISTER_COMPONENT_DESTRUCTOR_OP = 88 satisfies VmRegisterComponentDestructor; +export const VM_PUT_COMPONENT_OPERATIONS_OP = 89 satisfies VmPutComponentOperations; +export const VM_GET_COMPONENT_SELF_OP = 90 satisfies VmGetComponentSelf; +export const VM_GET_COMPONENT_TAG_NAME_OP = 91 satisfies VmGetComponentTagName; +export const VM_GET_COMPONENT_LAYOUT_OP = 92 satisfies VmGetComponentLayout; +export const VM_BIND_EVAL_SCOPE_OP = 93 satisfies VmBindEvalScope; +export const VM_SETUP_FOR_EVAL_OP = 94 satisfies VmSetupForEval; +export const VM_POPULATE_LAYOUT_OP = 95 satisfies VmPopulateLayout; +export const VM_INVOKE_COMPONENT_LAYOUT_OP = 96 satisfies VmInvokeComponentLayout; +export const VM_BEGIN_COMPONENT_TRANSACTION_OP = 97 satisfies VmBeginComponentTransaction; +export const VM_COMMIT_COMPONENT_TRANSACTION_OP = 98 satisfies VmCommitComponentTransaction; +export const VM_DID_CREATE_ELEMENT_OP = 99 satisfies VmDidCreateElement; +export const VM_DID_RENDER_LAYOUT_OP = 100 satisfies VmDidRenderLayout; +export const VM_DEBUGGER_OP = 103 satisfies VmDebugger; +export const VM_STATIC_COMPONENT_ATTR_OP = 105 satisfies VmStaticComponentAttr; +export const VM_DYNAMIC_CONTENT_TYPE_OP = 106 satisfies VmDynamicContentType; +export const VM_DYNAMIC_HELPER_OP = 107 satisfies VmDynamicHelper; +export const VM_DYNAMIC_MODIFIER_OP = 108 satisfies VmDynamicModifier; +export const VM_IF_INLINE_OP = 109 satisfies VmIfInline; +export const VM_NOT_OP = 110 satisfies VmNot; +export const VM_GET_DYNAMIC_VAR_OP = 111 satisfies VmGetDynamicVar; +export const VM_LOG_OP = 112 satisfies VmLog; +export const VM_SYSCALL_SIZE = 113 satisfies VmSize; + +export function isOp(value: number): value is VmOp { + return value >= 16; +} diff --git a/packages/@glimmer/constants/lib/vm-ops.ts b/packages/@glimmer/constants/lib/vm-ops.ts new file mode 100644 index 0000000000..883653498e --- /dev/null +++ b/packages/@glimmer/constants/lib/vm-ops.ts @@ -0,0 +1,24 @@ +import type { + VmMachineInvokeStatic, + VmMachineInvokeVirtual, + VmMachineJump, + VmMachineOp, + VmMachinePopFrame, + VmMachinePushFrame, + VmMachineReturn, + VmMachineReturnTo, + VmMachineSize, +} from '@glimmer/interfaces'; + +export const VM_PUSH_FRAME_OP = 0 satisfies VmMachinePushFrame; +export const VM_POP_FRAME_OP = 1 satisfies VmMachinePopFrame; +export const VM_INVOKE_VIRTUAL_OP = 2 satisfies VmMachineInvokeVirtual; +export const VM_INVOKE_STATIC_OP = 3 satisfies VmMachineInvokeStatic; +export const VM_JUMP_OP = 4 satisfies VmMachineJump; +export const VM_RETURN_OP = 5 satisfies VmMachineReturn; +export const VM_RETURN_TO_OP = 6 satisfies VmMachineReturnTo; +export const VM_MACHINE_SIZE = 7 satisfies VmMachineSize; + +export function isMachineOp(value: number): value is VmMachineOp { + return value >= 0 && value <= 15; +} diff --git a/packages/@glimmer/constants/package.json b/packages/@glimmer/constants/package.json new file mode 100644 index 0000000000..89ce463b88 --- /dev/null +++ b/packages/@glimmer/constants/package.json @@ -0,0 +1,30 @@ +{ + "name": "@glimmer/constants", + "private": true, + "version": "0.92.3", + "license": "MIT", + "description": "Constant values and functions that should be inlined and stripped from published builds. This package should not be published.", + "repository": "https://github.com/tildeio/glimmer/tree/main/packages/@glimmer/debug-util", + "type": "module", + "main": "index.ts", + "types": "index.ts", + "scripts": { + "test:lint": "eslint .", + "test:publint": "publint", + "test:types": "tsc --noEmit -p ../tsconfig.json" + }, + "dependencies": { + "@glimmer/env": "0.1.7", + "@glimmer/interfaces": "workspace:*" + }, + "devDependencies": { + "@glimmer-workspace/build-support": "workspace:*", + "@glimmer/debug-util": "workspace:*", + "@glimmer/local-debug-flags": "workspace:*", + "@types/qunit": "^2.19.9", + "eslint": "^8.52.0", + "publint": "^0.2.5", + "rollup": "^4.5.1", + "typescript": "*" + } +} diff --git a/packages/@glimmer/constants/test/debug-to-string-test.ts b/packages/@glimmer/constants/test/debug-to-string-test.ts new file mode 100644 index 0000000000..324b08b0da --- /dev/null +++ b/packages/@glimmer/constants/test/debug-to-string-test.ts @@ -0,0 +1,9 @@ +/// + +import { BLOCK_HEAD } from '@glimmer/constants'; + +QUnit.module('@glimmer/constants'); + +QUnit.test('BLOCK_HEAD', (assert) => { + assert.strictEqual(BLOCK_HEAD, 'Block'); +}); diff --git a/packages/@glimmer/util/test/immediate-test.ts b/packages/@glimmer/constants/test/immediate-test.ts similarity index 56% rename from packages/@glimmer/util/test/immediate-test.ts rename to packages/@glimmer/constants/test/immediate-test.ts index 30fdbf7f24..e996038c1c 100644 --- a/packages/@glimmer/util/test/immediate-test.ts +++ b/packages/@glimmer/constants/test/immediate-test.ts @@ -1,18 +1,23 @@ -import { decodeImmediate, encodeImmediate, ImmediateConstants } from '@glimmer/util'; +import { + decodeImmediate, + encodeImmediate, + MAX_INT, + MAX_SMI, + MIN_INT, + MIN_SMI, +} from '@glimmer/constants'; const { module, test } = QUnit; module('immediate encoding tests', () => { test('it works', (assert) => { - let cases = [ImmediateConstants.MIN_INT, -1, 0, ImmediateConstants.MAX_INT]; + let cases = [MIN_INT, -1, 0, MAX_INT]; for (const val of cases) { let encoded = encodeImmediate(val); assert.strictEqual(val, decodeImmediate(encoded), 'correctly encoded and decoded'); - const isSMI = - (encoded as ImmediateConstants) >= ImmediateConstants.MIN_SMI && - (encoded as ImmediateConstants) <= ImmediateConstants.MAX_SMI; + const isSMI = encoded >= MIN_SMI && encoded <= MAX_SMI; assert.true(isSMI, 'encoded as an SMI'); assert.step(`testing ${val}`); } diff --git a/packages/@glimmer/constants/test/package.json b/packages/@glimmer/constants/test/package.json new file mode 100644 index 0000000000..93ed9d8031 --- /dev/null +++ b/packages/@glimmer/constants/test/package.json @@ -0,0 +1,13 @@ +{ + "private": true, + "name": "@glimmer-test/constants", + "dependencies": { + "@glimmer/util": "workspace:*", + "@glimmer/env": "0.1.7" + }, + "devDependencies": { + "@glimmer/constants": "workspace:*", + "@glimmer/debug-util": "workspace:*", + "vite": "^5.4.10" + } +} diff --git a/packages/@glimmer/debug-util/lib/assert.ts b/packages/@glimmer/debug-util/lib/assert.ts index 302d79cbd7..56159703ab 100644 --- a/packages/@glimmer/debug-util/lib/assert.ts +++ b/packages/@glimmer/debug-util/lib/assert.ts @@ -19,16 +19,16 @@ export function deprecate(desc: string) { /** * This constant exists to make it easier to differentiate normal logs from * errant console.logs. LOCAL_LOGGER should only be used inside a - * LOCAL_SHOULD_LOG check. + * LOCAL_TRACE_LOGGING check. *FF - * It does not alleviate the need to check LOCAL_SHOULD_LOG, which is used + * It does not alleviate the need to check LOCAL_TRACE_LOGGING, which is used * for stripping. */ export const LOCAL_LOGGER = console; /** * This constant exists to make it easier to differentiate normal logs from - * errant console.logs. LOGGER can be used outside of LOCAL_SHOULD_LOG checks, + * errant console.logs. LOGGER can be used outside of LOCAL_TRACE_LOGGING checks, * and is meant to be used in the rare situation where a console.* call is * actually appropriate. */ diff --git a/packages/@glimmer/debug-util/rollup.config.mjs b/packages/@glimmer/debug-util/rollup.config.mjs deleted file mode 100644 index efe98fb212..0000000000 --- a/packages/@glimmer/debug-util/rollup.config.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import { Package } from '@glimmer-workspace/build-support'; - -export default Package.config(import.meta); diff --git a/packages/@glimmer/debug/index.ts b/packages/@glimmer/debug/index.ts index d8aa97aa18..3993b7c94c 100644 --- a/packages/@glimmer/debug/index.ts +++ b/packages/@glimmer/debug/index.ts @@ -23,16 +23,19 @@ export { CheckHandle, CheckInstanceof, CheckInterface, + CheckMachineRegister, CheckMaybe, CheckNode, + CheckNullable, CheckNumber, CheckObject, - CheckOption, CheckOr, CheckPrimitive, CheckProgramSymbolTable, + CheckRegister, CheckSafeString, CheckString, + CheckSyscallRegister, CheckUndefined, CheckUnknown, recordStackSize, diff --git a/packages/@glimmer/debug/lib/debug.ts b/packages/@glimmer/debug/lib/debug.ts index ad2ef20b2e..d9aae6f60f 100644 --- a/packages/@glimmer/debug/lib/debug.ts +++ b/packages/@glimmer/debug/lib/debug.ts @@ -7,9 +7,9 @@ import type { RuntimeOp, TemplateCompilationContext, } from '@glimmer/interfaces'; -import type { Register } from '@glimmer/vm'; -import { LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; -import { decodeHandle, decodeImmediate, enumerate, LOCAL_LOGGER } from '@glimmer/util'; +import { decodeHandle, decodeImmediate } from '@glimmer/constants'; +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; +import { enumerate, LOCAL_LOGGER } from '@glimmer/util'; import { $fp, $pc, $ra, $s0, $s1, $sp, $t0, $t1, $v0 } from '@glimmer/vm'; import type { Primitive } from './stack-check'; @@ -22,7 +22,7 @@ export interface DebugConstants { } export function debugSlice(context: TemplateCompilationContext, start: number, end: number) { - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { LOCAL_LOGGER.group(`%c${start}:${end}`, 'color: #999'); let heap = context.program.heap; @@ -39,7 +39,7 @@ export function debugSlice(context: TemplateCompilationContext, start: number, e opcode, opcode.isMachine )!; - LOCAL_LOGGER.log(`${i}. ${logOpcode(name, params)}`); + LOCAL_LOGGER.debug(`${i}. ${logOpcode(name, params)}`); _size = opcode.size; } opcode.offset = -_size; @@ -48,7 +48,7 @@ export function debugSlice(context: TemplateCompilationContext, start: number, e } export function logOpcode(type: string, params: Maybe): string | void { - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { let out = type; if (params) { @@ -62,7 +62,7 @@ export function logOpcode(type: string, params: Maybe): string | void { } function json(param: unknown) { - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { if (typeof param === 'function') { return ''; } @@ -92,7 +92,7 @@ export function debug( op: RuntimeOp, isMachine: 0 | 1 ): [string, Dict] | undefined { - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { let metadata = opcodeMetadata(op.type, isMachine); if (!metadata) { @@ -161,7 +161,7 @@ function opcodeOperand(opcode: RuntimeOp, index: number): number { } } -function decodeRegister(register: Register): string { +function decodeRegister(register: number): string { switch (register) { case $pc: return 'pc'; @@ -181,6 +181,8 @@ function decodeRegister(register: Register): string { return 't1'; case $v0: return 'v0'; + default: + throw new Error(`Unexpected register ${register}`); } } diff --git a/packages/@glimmer/debug/lib/opcode-metadata.ts b/packages/@glimmer/debug/lib/opcode-metadata.ts index a05c52d149..6ede3173d7 100644 --- a/packages/@glimmer/debug/lib/opcode-metadata.ts +++ b/packages/@glimmer/debug/lib/opcode-metadata.ts @@ -1,8 +1,107 @@ /* This file is generated by build/debug.js */ import type { Nullable, VmMachineOp, VmOp } from '@glimmer/interfaces'; +import { + VM_APPEND_DOCUMENT_FRAGMENT_OP, + VM_APPEND_HTML_OP, + VM_APPEND_NODE_OP, + VM_APPEND_SAFE_HTML_OP, + VM_APPEND_TEXT_OP, + VM_ASSERT_SAME_OP, + VM_BEGIN_COMPONENT_TRANSACTION_OP, + VM_BIND_DYNAMIC_SCOPE_OP, + VM_BIND_EVAL_SCOPE_OP, + VM_CAPTURE_ARGS_OP, + VM_CHILD_SCOPE_OP, + VM_CLOSE_ELEMENT_OP, + VM_COMMENT_OP, + VM_COMMIT_COMPONENT_TRANSACTION_OP, + VM_COMPILE_BLOCK_OP, + VM_COMPONENT_ATTR_OP, + VM_CONCAT_OP, + VM_CONSTANT_OP, + VM_CONSTANT_REFERENCE_OP, + VM_CONTENT_TYPE_OP, + VM_CREATE_COMPONENT_OP, + VM_CURRY_OP, + VM_DEBUGGER_OP, + VM_DID_CREATE_ELEMENT_OP, + VM_DID_RENDER_LAYOUT_OP, + VM_DUP_OP, + VM_DYNAMIC_ATTR_OP, + VM_DYNAMIC_CONTENT_TYPE_OP, + VM_DYNAMIC_HELPER_OP, + VM_ENTER_LIST_OP, + VM_ENTER_OP, + VM_EXIT_LIST_OP, + VM_EXIT_OP, + VM_FETCH_OP, + VM_FLUSH_ELEMENT_OP, + VM_GET_BLOCK_OP, + VM_GET_COMPONENT_LAYOUT_OP, + VM_GET_COMPONENT_SELF_OP, + VM_GET_COMPONENT_TAG_NAME_OP, + VM_GET_PROPERTY_OP, + VM_GET_VARIABLE_OP, + VM_HAS_BLOCK_OP, + VM_HAS_BLOCK_PARAMS_OP, + VM_HELPER_OP, + VM_IF_INLINE_OP, + VM_INVOKE_COMPONENT_LAYOUT_OP, + VM_INVOKE_STATIC_OP, + VM_INVOKE_VIRTUAL_OP, + VM_INVOKE_YIELD_OP, + VM_ITERATE_OP, + VM_JUMP_EQ_OP, + VM_JUMP_IF_OP, + VM_JUMP_OP, + VM_JUMP_UNLESS_OP, + VM_LOAD_OP, + VM_MACHINE_SIZE, + VM_MAIN_OP, + VM_MODIFIER_OP, + VM_NOT_OP, + VM_OPEN_DYNAMIC_ELEMENT_OP, + VM_OPEN_ELEMENT_OP, + VM_POP_ARGS_OP, + VM_POP_DYNAMIC_SCOPE_OP, + VM_POP_FRAME_OP, + VM_POP_OP, + VM_POP_REMOTE_ELEMENT_OP, + VM_POP_SCOPE_OP, + VM_POPULATE_LAYOUT_OP, + VM_PREPARE_ARGS_OP, + VM_PRIMITIVE_OP, + VM_PRIMITIVE_REFERENCE_OP, + VM_PUSH_ARGS_OP, + VM_PUSH_BLOCK_SCOPE_OP, + VM_PUSH_COMPONENT_DEFINITION_OP, + VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP, + VM_PUSH_DYNAMIC_SCOPE_OP, + VM_PUSH_EMPTY_ARGS_OP, + VM_PUSH_FRAME_OP, + VM_PUSH_REMOTE_ELEMENT_OP, + VM_PUSH_SYMBOL_TABLE_OP, + VM_PUT_COMPONENT_OPERATIONS_OP, + VM_REGISTER_COMPONENT_DESTRUCTOR_OP, + VM_REIFY_U32_OP, + VM_RESOLVE_DYNAMIC_COMPONENT_OP, + VM_RETURN_OP, + VM_RETURN_TO_OP, + VM_ROOT_SCOPE_OP, + VM_SET_BLOCK_OP, + VM_SET_BLOCKS_OP, + VM_SET_NAMED_VARIABLES_OP, + VM_SET_VARIABLE_OP, + VM_SETUP_FOR_EVAL_OP, + VM_SPREAD_BLOCK_OP, + VM_STATIC_ATTR_OP, + VM_SYSCALL_SIZE, + VM_TEXT_OP, + VM_TO_BOOLEAN_OP, + VM_VIRTUAL_ROOT_SCOPE_OP, +} from '@glimmer/constants'; import { LOCAL_DEBUG } from '@glimmer/local-debug-flags'; -import { MachineOp, Op } from '@glimmer/vm'; import type { NormalizedMetadata } from './metadata'; @@ -19,11 +118,11 @@ export function opcodeMetadata( return value || null; } -const METADATA: Nullable[] = new Array(Op.Size).fill(null); -const MACHINE_METADATA: Nullable[] = new Array(Op.Size).fill(null); +const METADATA: Nullable[] = new Array(VM_SYSCALL_SIZE).fill(null); +const MACHINE_METADATA: Nullable[] = new Array(VM_MACHINE_SIZE).fill(null); if (LOCAL_DEBUG) { - MACHINE_METADATA[MachineOp.PushFrame] = { + MACHINE_METADATA[VM_PUSH_FRAME_OP] = { name: 'PushFrame', mnemonic: 'pushf', before: null, @@ -33,7 +132,7 @@ if (LOCAL_DEBUG) { check: true, }; - MACHINE_METADATA[MachineOp.PopFrame] = { + MACHINE_METADATA[VM_POP_FRAME_OP] = { name: 'PopFrame', mnemonic: 'popf', before: null, @@ -43,7 +142,7 @@ if (LOCAL_DEBUG) { check: false, }; - MACHINE_METADATA[MachineOp.InvokeVirtual] = { + MACHINE_METADATA[VM_INVOKE_VIRTUAL_OP] = { name: 'InvokeVirtual', mnemonic: 'vcall', before: null, @@ -53,7 +152,7 @@ if (LOCAL_DEBUG) { check: true, }; - MACHINE_METADATA[MachineOp.InvokeStatic] = { + MACHINE_METADATA[VM_INVOKE_STATIC_OP] = { name: 'InvokeStatic', mnemonic: 'scall', before: null, @@ -68,7 +167,7 @@ if (LOCAL_DEBUG) { check: true, }; - MACHINE_METADATA[MachineOp.Jump] = { + MACHINE_METADATA[VM_JUMP_OP] = { name: 'Jump', mnemonic: 'goto', before: null, @@ -83,7 +182,7 @@ if (LOCAL_DEBUG) { check: true, }; - MACHINE_METADATA[MachineOp.Return] = { + MACHINE_METADATA[VM_RETURN_OP] = { name: 'Return', mnemonic: 'ret', before: null, @@ -93,7 +192,7 @@ if (LOCAL_DEBUG) { check: false, }; - MACHINE_METADATA[MachineOp.ReturnTo] = { + MACHINE_METADATA[VM_RETURN_TO_OP] = { name: 'ReturnTo', mnemonic: 'setra', before: null, @@ -107,7 +206,7 @@ if (LOCAL_DEBUG) { operands: 1, check: true, }; - METADATA[Op.Helper] = { + METADATA[VM_HELPER_OP] = { name: 'Helper', mnemonic: 'ncall', before: null, @@ -122,7 +221,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.DynamicHelper] = { + METADATA[VM_DYNAMIC_HELPER_OP] = { name: 'DynamicHelper', mnemonic: 'dynamiccall', before: null, @@ -132,7 +231,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.SetNamedVariables] = { + METADATA[VM_SET_NAMED_VARIABLES_OP] = { name: 'SetNamedVariables', mnemonic: 'vsargs', before: null, @@ -147,7 +246,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.SetBlocks] = { + METADATA[VM_SET_BLOCKS_OP] = { name: 'SetBlocks', mnemonic: 'vbblocks', before: null, @@ -162,7 +261,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.SetVariable] = { + METADATA[VM_SET_VARIABLE_OP] = { name: 'SetVariable', mnemonic: 'sbvar', before: null, @@ -177,7 +276,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.SetBlock] = { + METADATA[VM_SET_BLOCK_OP] = { name: 'SetBlock', mnemonic: 'sblock', before: null, @@ -192,7 +291,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.GetVariable] = { + METADATA[VM_GET_VARIABLE_OP] = { name: 'GetVariable', mnemonic: 'symload', before: null, @@ -207,7 +306,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.GetProperty] = { + METADATA[VM_GET_PROPERTY_OP] = { name: 'GetProperty', mnemonic: 'getprop', before: null, @@ -222,7 +321,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.GetBlock] = { + METADATA[VM_GET_BLOCK_OP] = { name: 'GetBlock', mnemonic: 'blockload', before: null, @@ -237,7 +336,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.SpreadBlock] = { + METADATA[VM_SPREAD_BLOCK_OP] = { name: 'SpreadBlock', mnemonic: 'blockspread', before: null, @@ -247,7 +346,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.HasBlock] = { + METADATA[VM_HAS_BLOCK_OP] = { name: 'HasBlock', mnemonic: 'hasblockload', before: null, @@ -257,7 +356,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.HasBlockParams] = { + METADATA[VM_HAS_BLOCK_PARAMS_OP] = { name: 'HasBlockParams', mnemonic: 'hasparamsload', before: null, @@ -267,7 +366,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Concat] = { + METADATA[VM_CONCAT_OP] = { name: 'Concat', mnemonic: 'concat', before: null, @@ -282,7 +381,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.IfInline] = { + METADATA[VM_IF_INLINE_OP] = { name: 'IfInline', mnemonic: 'ifinline', before: null, @@ -297,7 +396,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Not] = { + METADATA[VM_NOT_OP] = { name: 'Not', mnemonic: 'not', before: null, @@ -312,7 +411,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Constant] = { + METADATA[VM_CONSTANT_OP] = { name: 'Constant', mnemonic: 'rconstload', before: null, @@ -327,7 +426,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ConstantReference] = { + METADATA[VM_CONSTANT_REFERENCE_OP] = { name: 'ConstantReference', mnemonic: 'rconstrefload', before: null, @@ -342,7 +441,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Primitive] = { + METADATA[VM_PRIMITIVE_OP] = { name: 'Primitive', mnemonic: 'pconstload', before: null, @@ -357,7 +456,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PrimitiveReference] = { + METADATA[VM_PRIMITIVE_REFERENCE_OP] = { name: 'PrimitiveReference', mnemonic: 'ptoref', before: null, @@ -367,7 +466,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ReifyU32] = { + METADATA[VM_REIFY_U32_OP] = { name: 'ReifyU32', mnemonic: 'reifyload', before: null, @@ -377,7 +476,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Dup] = { + METADATA[VM_DUP_OP] = { name: 'Dup', mnemonic: 'dup', before: null, @@ -396,7 +495,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Pop] = { + METADATA[VM_POP_OP] = { name: 'Pop', mnemonic: 'pop', before: null, @@ -411,7 +510,7 @@ if (LOCAL_DEBUG) { check: false, }; - METADATA[Op.Load] = { + METADATA[VM_LOAD_OP] = { name: 'Load', mnemonic: 'put', before: null, @@ -426,7 +525,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Fetch] = { + METADATA[VM_FETCH_OP] = { name: 'Fetch', mnemonic: 'regload', before: null, @@ -441,7 +540,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.RootScope] = { + METADATA[VM_ROOT_SCOPE_OP] = { name: 'RootScope', mnemonic: 'rscopepush', before: null, @@ -456,7 +555,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.VirtualRootScope] = { + METADATA[VM_VIRTUAL_ROOT_SCOPE_OP] = { name: 'VirtualRootScope', mnemonic: 'vrscopepush', before: null, @@ -471,7 +570,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ChildScope] = { + METADATA[VM_CHILD_SCOPE_OP] = { name: 'ChildScope', mnemonic: 'cscopepush', before: null, @@ -481,7 +580,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PopScope] = { + METADATA[VM_POP_SCOPE_OP] = { name: 'PopScope', mnemonic: 'scopepop', before: null, @@ -491,7 +590,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Text] = { + METADATA[VM_TEXT_OP] = { name: 'Text', mnemonic: 'apnd_text', before: null, @@ -506,7 +605,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Comment] = { + METADATA[VM_COMMENT_OP] = { name: 'Comment', mnemonic: 'apnd_comment', before: null, @@ -521,7 +620,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.AppendHTML] = { + METADATA[VM_APPEND_HTML_OP] = { name: 'AppendHTML', mnemonic: 'apnd_dynhtml', before: null, @@ -531,7 +630,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.AppendSafeHTML] = { + METADATA[VM_APPEND_SAFE_HTML_OP] = { name: 'AppendSafeHTML', mnemonic: 'apnd_dynshtml', before: null, @@ -541,7 +640,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.AppendDocumentFragment] = { + METADATA[VM_APPEND_DOCUMENT_FRAGMENT_OP] = { name: 'AppendDocumentFragment', mnemonic: 'apnd_dynfrag', before: null, @@ -551,7 +650,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.AppendNode] = { + METADATA[VM_APPEND_NODE_OP] = { name: 'AppendNode', mnemonic: 'apnd_dynnode', before: null, @@ -561,7 +660,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.AppendText] = { + METADATA[VM_APPEND_TEXT_OP] = { name: 'AppendText', mnemonic: 'apnd_dyntext', before: null, @@ -571,7 +670,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.OpenElement] = { + METADATA[VM_OPEN_ELEMENT_OP] = { name: 'OpenElement', mnemonic: 'apnd_tag', before: null, @@ -586,7 +685,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.OpenDynamicElement] = { + METADATA[VM_OPEN_DYNAMIC_ELEMENT_OP] = { name: 'OpenDynamicElement', mnemonic: 'apnd_dyntag', before: null, @@ -596,7 +695,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PushRemoteElement] = { + METADATA[VM_PUSH_REMOTE_ELEMENT_OP] = { name: 'PushRemoteElement', mnemonic: 'apnd_remotetag', before: null, @@ -606,7 +705,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.StaticAttr] = { + METADATA[VM_STATIC_ATTR_OP] = { name: 'StaticAttr', mnemonic: 'apnd_attr', before: null, @@ -629,7 +728,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.DynamicAttr] = { + METADATA[VM_DYNAMIC_ATTR_OP] = { name: 'DynamicAttr', mnemonic: 'apnd_dynattr', before: null, @@ -652,7 +751,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ComponentAttr] = { + METADATA[VM_COMPONENT_ATTR_OP] = { name: 'ComponentAttr', mnemonic: 'apnd_cattr', before: null, @@ -675,7 +774,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.FlushElement] = { + METADATA[VM_FLUSH_ELEMENT_OP] = { name: 'FlushElement', mnemonic: 'apnd_flushtag', before: null, @@ -685,7 +784,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.CloseElement] = { + METADATA[VM_CLOSE_ELEMENT_OP] = { name: 'CloseElement', mnemonic: 'apnd_closetag', before: null, @@ -695,7 +794,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PopRemoteElement] = { + METADATA[VM_POP_REMOTE_ELEMENT_OP] = { name: 'PopRemoteElement', mnemonic: 'apnd_closeremotetag', before: null, @@ -705,7 +804,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Modifier] = { + METADATA[VM_MODIFIER_OP] = { name: 'Modifier', mnemonic: 'apnd_modifier', before: null, @@ -720,7 +819,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.BindDynamicScope] = { + METADATA[VM_BIND_DYNAMIC_SCOPE_OP] = { name: 'BindDynamicScope', mnemonic: 'setdynscope', before: null, @@ -735,7 +834,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PushDynamicScope] = { + METADATA[VM_PUSH_DYNAMIC_SCOPE_OP] = { name: 'PushDynamicScope', mnemonic: 'dynscopepush', before: null, @@ -745,7 +844,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PopDynamicScope] = { + METADATA[VM_POP_DYNAMIC_SCOPE_OP] = { name: 'PopDynamicScope', mnemonic: 'dynscopepop', before: null, @@ -755,7 +854,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.CompileBlock] = { + METADATA[VM_COMPILE_BLOCK_OP] = { name: 'CompileBlock', mnemonic: 'cmpblock', before: null, @@ -765,7 +864,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PushBlockScope] = { + METADATA[VM_PUSH_BLOCK_SCOPE_OP] = { name: 'PushBlockScope', mnemonic: 'scopeload', before: null, @@ -780,7 +879,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PushSymbolTable] = { + METADATA[VM_PUSH_SYMBOL_TABLE_OP] = { name: 'PushSymbolTable', mnemonic: 'dsymload', before: null, @@ -795,7 +894,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.InvokeYield] = { + METADATA[VM_INVOKE_YIELD_OP] = { name: 'InvokeYield', mnemonic: 'invokeyield', before: null, @@ -805,7 +904,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.JumpIf] = { + METADATA[VM_JUMP_IF_OP] = { name: 'JumpIf', mnemonic: 'iftrue', before: null, @@ -820,7 +919,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.JumpUnless] = { + METADATA[VM_JUMP_UNLESS_OP] = { name: 'JumpUnless', mnemonic: 'iffalse', before: null, @@ -835,7 +934,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.JumpEq] = { + METADATA[VM_JUMP_EQ_OP] = { name: 'JumpEq', mnemonic: 'ifeq', before: null, @@ -854,7 +953,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.AssertSame] = { + METADATA[VM_ASSERT_SAME_OP] = { name: 'AssertSame', mnemonic: 'assert_eq', before: null, @@ -864,7 +963,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Enter] = { + METADATA[VM_ENTER_OP] = { name: 'Enter', mnemonic: 'blk_start', before: null, @@ -879,7 +978,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Exit] = { + METADATA[VM_EXIT_OP] = { name: 'Exit', mnemonic: 'blk_end', before: null, @@ -889,7 +988,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ToBoolean] = { + METADATA[VM_TO_BOOLEAN_OP] = { name: 'ToBoolean', mnemonic: 'anytobool', before: null, @@ -899,7 +998,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.EnterList] = { + METADATA[VM_ENTER_LIST_OP] = { name: 'EnterList', mnemonic: 'list_start', before: null, @@ -918,7 +1017,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ExitList] = { + METADATA[VM_EXIT_LIST_OP] = { name: 'ExitList', mnemonic: 'list_end', before: null, @@ -928,7 +1027,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Iterate] = { + METADATA[VM_ITERATE_OP] = { name: 'Iterate', mnemonic: 'iter', before: null, @@ -943,7 +1042,7 @@ if (LOCAL_DEBUG) { check: false, }; - METADATA[Op.Main] = { + METADATA[VM_MAIN_OP] = { name: 'Main', mnemonic: 'main', before: null, @@ -958,7 +1057,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ContentType] = { + METADATA[VM_CONTENT_TYPE_OP] = { name: 'ContentType', mnemonic: 'ctload', before: null, @@ -968,7 +1067,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.DynamicContentType] = { + METADATA[VM_DYNAMIC_CONTENT_TYPE_OP] = { name: 'DynamicContentType', mnemonic: 'dctload', before: null, @@ -978,7 +1077,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.Curry] = { + METADATA[VM_CURRY_OP] = { name: 'Curry', mnemonic: 'curry', before: null, @@ -997,7 +1096,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PushComponentDefinition] = { + METADATA[VM_PUSH_COMPONENT_DEFINITION_OP] = { name: 'PushComponentDefinition', mnemonic: 'cmload', before: null, @@ -1012,7 +1111,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PushDynamicComponentInstance] = { + METADATA[VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP] = { name: 'PushDynamicComponentInstance', mnemonic: 'dciload', before: null, @@ -1022,7 +1121,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ResolveDynamicComponent] = { + METADATA[VM_RESOLVE_DYNAMIC_COMPONENT_OP] = { name: 'ResolveDynamicComponent', mnemonic: 'cdload', before: null, @@ -1037,7 +1136,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PushArgs] = { + METADATA[VM_PUSH_ARGS_OP] = { name: 'PushArgs', mnemonic: 'argsload', before: null, @@ -1060,7 +1159,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PushEmptyArgs] = { + METADATA[VM_PUSH_EMPTY_ARGS_OP] = { name: 'PushEmptyArgs', mnemonic: 'emptyargsload', before: null, @@ -1070,7 +1169,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PopArgs] = { + METADATA[VM_POP_ARGS_OP] = { name: 'PopArgs', mnemonic: 'argspop', before: null, @@ -1080,7 +1179,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PrepareArgs] = { + METADATA[VM_PREPARE_ARGS_OP] = { name: 'PrepareArgs', mnemonic: 'argsprep', before: null, @@ -1095,7 +1194,7 @@ if (LOCAL_DEBUG) { check: false, }; - METADATA[Op.CaptureArgs] = { + METADATA[VM_CAPTURE_ARGS_OP] = { name: 'CaptureArgs', mnemonic: 'argscapture', before: null, @@ -1105,7 +1204,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.CreateComponent] = { + METADATA[VM_CREATE_COMPONENT_OP] = { name: 'CreateComponent', mnemonic: 'comp_create', before: null, @@ -1124,7 +1223,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.RegisterComponentDestructor] = { + METADATA[VM_REGISTER_COMPONENT_DESTRUCTOR_OP] = { name: 'RegisterComponentDestructor', mnemonic: 'comp_dest', before: null, @@ -1139,7 +1238,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PutComponentOperations] = { + METADATA[VM_PUT_COMPONENT_OPERATIONS_OP] = { name: 'PutComponentOperations', mnemonic: 'comp_elops', before: null, @@ -1149,7 +1248,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.GetComponentSelf] = { + METADATA[VM_GET_COMPONENT_SELF_OP] = { name: 'GetComponentSelf', mnemonic: 'comp_selfload', before: null, @@ -1164,7 +1263,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.GetComponentTagName] = { + METADATA[VM_GET_COMPONENT_TAG_NAME_OP] = { name: 'GetComponentTagName', mnemonic: 'comp_tagload', before: null, @@ -1179,7 +1278,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.GetComponentLayout] = { + METADATA[VM_GET_COMPONENT_LAYOUT_OP] = { name: 'GetComponentLayout', mnemonic: 'comp_layoutload', before: null, @@ -1194,7 +1293,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.BindEvalScope] = { + METADATA[VM_BIND_EVAL_SCOPE_OP] = { name: 'BindEvalScope', mnemonic: 'eval_scope', before: null, @@ -1209,7 +1308,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.SetupForEval] = { + METADATA[VM_SETUP_FOR_EVAL_OP] = { name: 'SetupForEval', mnemonic: 'eval_setup', before: null, @@ -1224,7 +1323,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.PopulateLayout] = { + METADATA[VM_POPULATE_LAYOUT_OP] = { name: 'PopulateLayout', mnemonic: 'comp_layoutput', before: null, @@ -1239,7 +1338,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.InvokeComponentLayout] = { + METADATA[VM_INVOKE_COMPONENT_LAYOUT_OP] = { name: 'InvokeComponentLayout', mnemonic: 'comp_invokelayout', before: null, @@ -1254,7 +1353,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.BeginComponentTransaction] = { + METADATA[VM_BEGIN_COMPONENT_TRANSACTION_OP] = { name: 'BeginComponentTransaction', mnemonic: 'comp_begin', before: null, @@ -1264,7 +1363,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.CommitComponentTransaction] = { + METADATA[VM_COMMIT_COMPONENT_TRANSACTION_OP] = { name: 'CommitComponentTransaction', mnemonic: 'comp_commit', before: null, @@ -1274,7 +1373,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.DidCreateElement] = { + METADATA[VM_DID_CREATE_ELEMENT_OP] = { name: 'DidCreateElement', mnemonic: 'comp_created', before: null, @@ -1289,7 +1388,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.DidRenderLayout] = { + METADATA[VM_DID_RENDER_LAYOUT_OP] = { name: 'DidRenderLayout', mnemonic: 'comp_rendered', before: null, @@ -1304,22 +1403,7 @@ if (LOCAL_DEBUG) { check: true, }; - METADATA[Op.ResolveMaybeLocal] = { - name: 'ResolveMaybeLocal', - mnemonic: 'eval_varload', - before: null, - stackChange: 1, - ops: [ - { - name: 'local', - type: 'str', - }, - ], - operands: 1, - check: true, - }; - - METADATA[Op.Debugger] = { + METADATA[VM_DEBUGGER_OP] = { name: 'Debugger', mnemonic: 'debugger', before: null, diff --git a/packages/@glimmer/debug/lib/stack-check.ts b/packages/@glimmer/debug/lib/stack-check.ts index 19ef8a4139..e8853beacb 100644 --- a/packages/@glimmer/debug/lib/stack-check.ts +++ b/packages/@glimmer/debug/lib/stack-check.ts @@ -8,7 +8,9 @@ import type { SimpleElement, SimpleNode, } from '@glimmer/interfaces'; +import type { MachineRegister, Register, SyscallRegister } from '@glimmer/vm'; import { LOCAL_DEBUG } from '@glimmer/local-debug-flags'; +import { $fp, $pc, $ra, $s0, $s1, $sp, $t0, $t1, $v0 } from '@glimmer/vm'; export interface Checker { type: T; @@ -308,7 +310,67 @@ export function CheckInstanceof(Class: Constructor): Checker { return new InstanceofChecker(Class); } -export function CheckOption(checker: Checker): Checker> { +export const CheckRegister: Checker = new (class { + declare type: Register; + validate(value: unknown): value is Register { + switch (value) { + case $s0: + case $s1: + case $sp: + case $fp: + case $ra: + case $pc: + case $t0: + case $t1: + case $v0: + return true; + default: + return false; + } + } + expected(): string { + return `Register`; + } +})(); + +export const CheckSyscallRegister: Checker = new (class { + declare type: SyscallRegister; + validate(value: unknown): value is SyscallRegister { + switch (value) { + case $s0: + case $s1: + case $t0: + case $t1: + case $v0: + return true; + default: + return false; + } + } + expected(): string { + return `syscall register ($s0, $s1, $t0, $t1, $v0)`; + } +})(); + +export const CheckMachineRegister: Checker = new (class { + declare type: MachineRegister; + validate(value: unknown): value is MachineRegister { + switch (value) { + case $sp: + case $fp: + case $ra: + case $pc: + return true; + default: + return false; + } + } + expected(): string { + return `machine register ($sp, $fp, $ra, $pc)`; + } +})(); + +export function CheckNullable(checker: Checker): Checker> { if (!LOCAL_DEBUG) { return new NoopChecker(); } diff --git a/packages/@glimmer/debug/package.json b/packages/@glimmer/debug/package.json index 04cec452e3..4066d39a5b 100644 --- a/packages/@glimmer/debug/package.json +++ b/packages/@glimmer/debug/package.json @@ -19,6 +19,7 @@ }, "devDependencies": { "@glimmer-workspace/build-support": "workspace:*", + "@glimmer/constants": "workspace:*", "@glimmer/debug-util": "workspace:*", "@glimmer/local-debug-flags": "workspace:*", "eslint": "^8.52.0", diff --git a/packages/@glimmer/debug/rollup.config.mjs b/packages/@glimmer/debug/rollup.config.mjs deleted file mode 100644 index efe98fb212..0000000000 --- a/packages/@glimmer/debug/rollup.config.mjs +++ /dev/null @@ -1,3 +0,0 @@ -import { Package } from '@glimmer-workspace/build-support'; - -export default Package.config(import.meta); diff --git a/packages/@glimmer/destroyable/index.ts b/packages/@glimmer/destroyable/index.ts index afc85b2912..517c429535 100644 --- a/packages/@glimmer/destroyable/index.ts +++ b/packages/@glimmer/destroyable/index.ts @@ -2,11 +2,10 @@ import type { Destroyable, Destructor } from '@glimmer/interfaces'; import { debugToString } from '@glimmer/debug-util'; import { scheduleDestroy, scheduleDestroyed } from '@glimmer/global-context'; -const enum DestroyingState { - Live = 0, - Destroying = 1, - Destroyed = 2, -} +const LIVE_STATE = 0; +const DESTROYING_STATE = 1; +const DESTROYED_STATE = 2; +type DestroyableState = 0 | 1 | 2; type OneOrMany = null | T | T[]; @@ -16,7 +15,7 @@ interface DestroyableMeta { children: OneOrMany; eagerDestructors: OneOrMany>; destructors: OneOrMany>; - state: DestroyingState; + state: DestroyableState; } interface UndestroyedDestroyablesError extends Error { @@ -74,7 +73,7 @@ function getDestroyableMeta(destroyable: T): DestroyableM children: null, eagerDestructors: null, destructors: null, - state: DestroyingState.Live, + state: LIVE_STATE, }; if (import.meta.env.DEV) { @@ -153,11 +152,11 @@ export function unregisterDestructor( export function destroy(destroyable: Destroyable) { let meta = getDestroyableMeta(destroyable); - if (meta.state >= DestroyingState.Destroying) return; + if (meta.state >= DESTROYING_STATE) return; let { parents, children, eagerDestructors, destructors } = meta; - meta.state = DestroyingState.Destroying; + meta.state = DESTROYING_STATE; iterate(children, destroy); iterate(eagerDestructors, (destructor) => destructor(destroyable)); @@ -166,14 +165,14 @@ export function destroy(destroyable: Destroyable) { scheduleDestroyed(() => { iterate(parents, (parent) => removeChildFromParent(destroyable, parent)); - meta.state = DestroyingState.Destroyed; + meta.state = DESTROYED_STATE; }); } function removeChildFromParent(child: Destroyable, parent: Destroyable) { let parentMeta = getDestroyableMeta(parent); - if (parentMeta.state === DestroyingState.Live) { + if (parentMeta.state === LIVE_STATE) { parentMeta.children = remove( parentMeta.children, child, @@ -198,13 +197,13 @@ export function _hasDestroyableChildren(destroyable: Destroyable) { export function isDestroying(destroyable: Destroyable) { let meta = DESTROYABLE_META.get(destroyable); - return meta === undefined ? false : meta.state >= DestroyingState.Destroying; + return meta === undefined ? false : meta.state >= DESTROYING_STATE; } export function isDestroyed(destroyable: Destroyable) { let meta = DESTROYABLE_META.get(destroyable); - return meta === undefined ? false : meta.state >= DestroyingState.Destroyed; + return meta === undefined ? false : meta.state >= DESTROYED_STATE; } //////////// @@ -243,7 +242,7 @@ if (import.meta.env.DEV) { let undestroyed: object[] = []; map.forEach((meta) => { - if (meta.state !== DestroyingState.Destroyed) { + if (meta.state !== DESTROYED_STATE) { undestroyed.push(meta.source!); } }); diff --git a/packages/@glimmer/interfaces/lib/serialize.d.ts b/packages/@glimmer/interfaces/lib/serialize.d.ts index b40be8868a..ee6a89dd8e 100644 --- a/packages/@glimmer/interfaces/lib/serialize.d.ts +++ b/packages/@glimmer/interfaces/lib/serialize.d.ts @@ -75,13 +75,6 @@ export interface ResolvedComponentDefinition< template: Template | null; } -export enum ResolverContext { - Component, - Modifier, - Helper, - HelperOrComponent, -} - export interface CompileTimeResolver { lookupHelper(name: string, owner: O): Nullable; lookupModifier(name: string, owner: O): Nullable; diff --git a/packages/@glimmer/interfaces/lib/vm-opcodes.d.ts b/packages/@glimmer/interfaces/lib/vm-opcodes.d.ts index c428f832fc..9d9522e7d3 100644 --- a/packages/@glimmer/interfaces/lib/vm-opcodes.d.ts +++ b/packages/@glimmer/interfaces/lib/vm-opcodes.d.ts @@ -104,9 +104,7 @@ export type VmBeginComponentTransaction = 97; export type VmCommitComponentTransaction = 98; export type VmDidCreateElement = 99; export type VmDidRenderLayout = 100; -export type VmResolveMaybeLocal = 102; export type VmDebugger = 103; -export type VmSize = 104; export type VmStaticComponentAttr = 105; export type VmDynamicContentType = 106; export type VmDynamicHelper = 107; @@ -115,6 +113,7 @@ export type VmIfInline = 109; export type VmNot = 110; export type VmGetDynamicVar = 111; export type VmLog = 112; +export type VmSize = 113; export type VmOp = | VmHelper @@ -202,7 +201,6 @@ export type VmOp = | VmCommitComponentTransaction | VmDidCreateElement | VmDidRenderLayout - | VmResolveMaybeLocal | VmDebugger | VmSize | VmStaticComponentAttr diff --git a/packages/@glimmer/local-debug-flags/index.ts b/packages/@glimmer/local-debug-flags/index.ts index 7386945b99..b6b69e4833 100644 --- a/packages/@glimmer/local-debug-flags/index.ts +++ b/packages/@glimmer/local-debug-flags/index.ts @@ -1,23 +1,171 @@ -export const LOCAL_DEBUG: true | false = - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - import.meta.env.VM_LOCAL_DEV && - (() => { - let location = typeof window !== 'undefined' && window.location; - if (location && /[&?]disable_local_debug/u.test(window.location.search)) { - return false; +/* eslint-disable no-console */ + +declare global { + interface ImportMetaEnv { + VM_LOCAL_DEV?: boolean; + } +} + +// All of these flags are expected to become constant `false` in production builds. +export const LOCAL_DEBUG = import.meta.env.VM_LOCAL_DEV && !hasFlag('disable_local_debug'); +export const LOCAL_TRACE_LOGGING = import.meta.env.VM_LOCAL_DEV && hasFlag('enable_trace_logging'); +export const LOCAL_EXPLAIN_LOGGING = + import.meta.env.VM_LOCAL_DEV && hasFlag('enable_trace_explanations'); +export const LOCAL_INTERNALS_LOGGING = + import.meta.env.VM_LOCAL_DEV && hasFlag('enable_internals_logging'); +export const LOCAL_SUBTLE_LOGGING = + import.meta.env.VM_LOCAL_DEV && hasFlag('enable_subtle_logging'); + +if (LOCAL_INTERNALS_LOGGING || LOCAL_EXPLAIN_LOGGING) { + console.group('%cLogger Flags:', 'font-weight: normal; color: teal'); + log( + 'LOCAL_DEBUG', + LOCAL_DEBUG, + 'Enables debug logging for people working on this repository. If this is off, none of the other flags will do anything.' + ); + log( + 'LOCAL_TRACE_LOGGING', + LOCAL_TRACE_LOGGING, + `Enables trace logging. This is most useful if you're working on the internals, and includes a trace of compiled templates and a trace of VM execution that includes state changes. If you want to see all of the state, enable LOCAL_SUBTLE_LOGGING.` + ); + log( + 'LOCAL_EXPLAIN_LOGGING', + LOCAL_EXPLAIN_LOGGING, + 'Enables trace explanations (like this one!)' + ); + log( + 'LOCAL_INTERNALS_LOGGING', + LOCAL_INTERNALS_LOGGING, + `Enables logging of internal state. This is most useful if you're working on the debug infrastructure itself.` + ); + log( + 'LOCAL_SUBTLE_LOGGING', + LOCAL_SUBTLE_LOGGING, + 'Enables more complete logging, even when the result would be extremely verbose and not usually necessary. Subtle logs are dimmed when enabled.' + ); + log( + 'audit_logging', + getFlag('audit_logging'), + 'Enables specific audit logs. These logs are useful during an internal refactor and can help pinpoint exactly where legacy code is being used.' + ); + log( + 'focus_highlight', + getFlag('focus_highlight'), + `Enables focus highlighting of specific trace logs. This makes it easy to see specific aspects of the trace at a glance.` + ); + console.log(); + console.groupEnd(); + + function log(flag: string, value: boolean | string | string[] | undefined, explanation: string) { + const { formatted, style } = format(value); + + const header = [ + `%c[${flag}]%c %c${formatted}`, + `font-weight: normal; background-color: ${style}; color: white`, + ``, + `font-weight: normal; color: ${style}`, + ]; + + if (LOCAL_EXPLAIN_LOGGING) { + console.group(...header); + console.log(`%c${explanation}`, 'color: grey'); + console.groupEnd(); + } else { + console.log(...header); } - return true; - })(); - -export const LOCAL_SHOULD_LOG: true | false = - // eslint-disable-next-line @typescript-eslint/ban-ts-comment - // @ts-ignore - import.meta.env.VM_LOCAL_DEV && - (() => { - let location = typeof window !== 'undefined' && window.location; - if (location && /[&?]enable_local_should_log/u.test(window.location.search)) { - return true; + } + + function format(flagValue: boolean | string | string[] | undefined): { + formatted: string; + style: string; + } { + if (flagValue === undefined || flagValue === false) { + return { formatted: 'off', style: 'grey' }; + } else if (flagValue === true) { + return { formatted: 'on', style: 'green' }; + } else if (typeof flagValue === 'string') { + return { formatted: flagValue, style: 'blue' }; + } else if (Array.isArray(flagValue)) { + if (flagValue.length === 0) { + return { formatted: 'none', style: 'grey' }; + } + return { formatted: `[${flagValue.join(', ')}]`, style: 'teal' }; + } else { + assertNever(flagValue); } + } + + function assertNever(_never: never): never { + throw new Error('unreachable'); + } +} + +// This function should turn into a constant `return false` in `import.meta.env.PROD`, +// which should inline properly via terser, swc and esbuild. +// +// https://tiny.katz.zone/BNqN3F +function hasFlag(flag: string): true | false { + if (import.meta.env.VM_LOCAL_DEV) { + const url = + typeof window !== 'undefined' && window.location ? new URL(window.location.href) : null; + + return url?.searchParams.has(flag) ?? false; + } else { return false; - })(); + } +} + +if (import.meta.env.VM_LOCAL_DEV) { + Error.stackTraceLimit = Infinity; +} + +/** + * If the specified flag is set as a boolean flag with no value, `true` is returned. + * + * Otherwise, this function returns true if the flag value is a pattern that matches `value`. + * + * The pattern can have a `*`, which matches any number of characters. + */ +export function hasFlagWith(flag: string, value: string): boolean { + if (import.meta.env.VM_LOCAL_DEV) { + const url = + typeof window !== 'undefined' && window.location ? new URL(window.location.href) : null; + + const pattern = new RegExp(`^${value.replace(/\*/gu, '.*')}$`, 'u'); + + return url?.searchParams.getAll(flag).some((param) => pattern.test(param)) ?? false; + } else { + return false; + } +} + +export function getFlagValues(flag: string): string[] { + if (import.meta.env.VM_LOCAL_DEV) { + const url = + typeof window !== 'undefined' && window.location ? new URL(window.location.href) : null; + + const all = url?.searchParams.getAll(flag); + return all?.filter((a) => a !== '') ?? []; + } else { + return []; + } +} + +export function getFlag(flag: string): boolean | string | string[] | undefined { + if (import.meta.env.VM_LOCAL_DEV) { + const url = + typeof window !== 'undefined' && window.location ? new URL(window.location.href) : null; + + const all = url?.searchParams.getAll(flag); + + if (all) { + if (all.length === 1) { + return all[0] === '' ? true : all[0]; + } else { + return all; + } + } + } else { + return undefined; + } +} diff --git a/packages/@glimmer/opcode-compiler/lib/compilable-template.ts b/packages/@glimmer/opcode-compiler/lib/compilable-template.ts index 554317f1d6..471877b60c 100644 --- a/packages/@glimmer/opcode-compiler/lib/compilable-template.ts +++ b/packages/@glimmer/opcode-compiler/lib/compilable-template.ts @@ -16,7 +16,7 @@ import type { SymbolTable, WireFormat, } from '@glimmer/interfaces'; -import { LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import { EMPTY_ARRAY } from '@glimmer/util'; import type { HighLevelStatementOp } from './syntax/compilers'; @@ -99,7 +99,7 @@ export function compileStatements( let handle = context.encoder.commit(meta.size); - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { debugCompiler(context, handle); } diff --git a/packages/@glimmer/opcode-compiler/lib/compiler.ts b/packages/@glimmer/opcode-compiler/lib/compiler.ts index b1f8db0d7a..fb259fae9e 100644 --- a/packages/@glimmer/opcode-compiler/lib/compiler.ts +++ b/packages/@glimmer/opcode-compiler/lib/compiler.ts @@ -1,11 +1,11 @@ import type { HandleResult, TemplateCompilationContext } from '@glimmer/interfaces'; import { debugSlice } from '@glimmer/debug'; import { extractHandle } from '@glimmer/debug-util'; -import { LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; export let debugCompiler: (context: TemplateCompilationContext, handle: HandleResult) => void; -if (LOCAL_SHOULD_LOG) { +if (LOCAL_TRACE_LOGGING) { debugCompiler = (context: TemplateCompilationContext, result: HandleResult) => { let handle = extractHandle(result); let { heap } = context.program; diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/encoder.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/encoder.ts index 90fd7676b8..0305c0f96e 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/encoder.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/encoder.ts @@ -16,10 +16,11 @@ import type { SingleBuilderOperand, STDLib, } from '@glimmer/interfaces'; +import { encodeHandle, isMachineOp, VM_PRIMITIVE_OP, VM_RETURN_OP } from '@glimmer/constants'; import { assert, expect, isPresentArray } from '@glimmer/debug-util'; import { InstructionEncoderImpl } from '@glimmer/encoder'; -import { dict, EMPTY_STRING_ARRAY, encodeHandle, Stack } from '@glimmer/util'; -import { ARG_SHIFT, isMachineOp, MACHINE_MASK, MachineOp, Op, TYPE_SIZE } from '@glimmer/vm'; +import { dict, EMPTY_STRING_ARRAY, Stack } from '@glimmer/util'; +import { ARG_SHIFT, MACHINE_MASK, TYPE_SIZE } from '@glimmer/vm'; import { compilableBlock } from '../compilable-template'; import { @@ -131,14 +132,14 @@ export class EncoderImpl implements Encoder { } error(error: EncoderError): void { - this.encoder.encode(Op.Primitive, 0); + this.encoder.encode(VM_PRIMITIVE_OP, 0); this.errors.push(error); } commit(size: number): HandleResult { let handle = this.handle; - this.heap.pushMachine(MachineOp.Return); + this.heap.pushMachine(VM_RETURN_OP); this.heap.finishMalloc(handle, size); if (isPresentArray(this.errors)) { diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/blocks.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/blocks.ts index 8bdd60909b..95c2d5d96e 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/blocks.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/blocks.ts @@ -1,5 +1,21 @@ import type { Nullable, WireFormat } from '@glimmer/interfaces'; -import { $fp, MachineOp, Op } from '@glimmer/vm'; +import { + VM_CHILD_SCOPE_OP, + VM_COMPILE_BLOCK_OP, + VM_CONSTANT_OP, + VM_DUP_OP, + VM_GET_BLOCK_OP, + VM_INVOKE_VIRTUAL_OP, + VM_INVOKE_YIELD_OP, + VM_POP_FRAME_OP, + VM_POP_SCOPE_OP, + VM_PUSH_BLOCK_SCOPE_OP, + VM_PUSH_FRAME_OP, + VM_PUSH_SYMBOL_TABLE_OP, + VM_SET_VARIABLE_OP, + VM_SPREAD_BLOCK_OP, +} from '@glimmer/constants'; +import { $fp } from '@glimmer/vm'; import type { PushExpressionOp, PushStatementOp } from '../../syntax/compilers'; @@ -19,12 +35,12 @@ export function YieldBlock( positional: Nullable ): void { SimpleArgs(op, positional, null, true); - op(Op.GetBlock, to); - op(Op.SpreadBlock); - op(Op.CompileBlock); - op(Op.InvokeYield); - op(Op.PopScope); - op(MachineOp.PopFrame); + op(VM_GET_BLOCK_OP, to); + op(VM_SPREAD_BLOCK_OP); + op(VM_COMPILE_BLOCK_OP); + op(VM_INVOKE_YIELD_OP); + op(VM_POP_SCOPE_OP); + op(VM_POP_FRAME_OP); } /** @@ -38,7 +54,7 @@ export function PushYieldableBlock( block: Nullable ): void { PushSymbolTable(op, block && block[1]); - op(Op.PushBlockScope); + op(VM_PUSH_BLOCK_SCOPE_OP); PushCompilable(op, block); } @@ -51,11 +67,11 @@ export function InvokeStaticBlock( op: PushStatementOp, block: WireFormat.SerializedInlineBlock ): void { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); PushCompilable(op, block); - op(Op.CompileBlock); - op(MachineOp.InvokeVirtual); - op(MachineOp.PopFrame); + op(VM_COMPILE_BLOCK_OP); + op(VM_INVOKE_VIRTUAL_OP); + op(VM_POP_FRAME_OP); } /** @@ -79,31 +95,31 @@ export function InvokeStaticBlockWithStack( return; } - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); if (count) { - op(Op.ChildScope); + op(VM_CHILD_SCOPE_OP); for (let i = 0; i < count; i++) { - op(Op.Dup, $fp, callerCount - i); - op(Op.SetVariable, parameters[i]); + op(VM_DUP_OP, $fp, callerCount - i); + op(VM_SET_VARIABLE_OP, parameters[i]); } } PushCompilable(op, block); - op(Op.CompileBlock); - op(MachineOp.InvokeVirtual); + op(VM_COMPILE_BLOCK_OP); + op(VM_INVOKE_VIRTUAL_OP); if (count) { - op(Op.PopScope); + op(VM_POP_SCOPE_OP); } - op(MachineOp.PopFrame); + op(VM_POP_FRAME_OP); } export function PushSymbolTable(op: PushExpressionOp, parameters: number[] | null): void { if (parameters !== null) { - op(Op.PushSymbolTable, symbolTableOperand({ parameters })); + op(VM_PUSH_SYMBOL_TABLE_OP, symbolTableOperand({ parameters })); } else { PushPrimitive(op, null); } @@ -116,6 +132,6 @@ export function PushCompilable( if (_block === null) { PushPrimitive(op, null); } else { - op(Op.Constant, blockOperand(_block)); + op(VM_CONSTANT_OP, blockOperand(_block)); } } diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/components.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/components.ts index 9d52316de2..d04bd89f08 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/components.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/components.ts @@ -8,10 +8,56 @@ import type { WireFormat, } from '@glimmer/interfaces'; import type { SavedRegister } from '@glimmer/vm'; +import { + VM_BEGIN_COMPONENT_TRANSACTION_OP, + VM_CLOSE_ELEMENT_OP, + VM_COMMIT_COMPONENT_TRANSACTION_OP, + VM_COMPILE_BLOCK_OP, + VM_CONSTANT_OP, + VM_CREATE_COMPONENT_OP, + VM_DID_CREATE_ELEMENT_OP, + VM_DID_RENDER_LAYOUT_OP, + VM_DUP_OP, + VM_FETCH_OP, + VM_FLUSH_ELEMENT_OP, + VM_GET_COMPONENT_LAYOUT_OP, + VM_GET_COMPONENT_SELF_OP, + VM_GET_COMPONENT_TAG_NAME_OP, + VM_INVOKE_COMPONENT_LAYOUT_OP, + VM_INVOKE_VIRTUAL_OP, + VM_JUMP_UNLESS_OP, + VM_LOAD_OP, + VM_OPEN_DYNAMIC_ELEMENT_OP, + VM_POP_DYNAMIC_SCOPE_OP, + VM_POP_FRAME_OP, + VM_POP_OP, + VM_POP_SCOPE_OP, + VM_POPULATE_LAYOUT_OP, + VM_PREPARE_ARGS_OP, + VM_PRIMITIVE_REFERENCE_OP, + VM_PUSH_ARGS_OP, + VM_PUSH_COMPONENT_DEFINITION_OP, + VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP, + VM_PUSH_DYNAMIC_SCOPE_OP, + VM_PUSH_EMPTY_ARGS_OP, + VM_PUSH_FRAME_OP, + VM_PUSH_SYMBOL_TABLE_OP, + VM_PUT_COMPONENT_OPERATIONS_OP, + VM_REGISTER_COMPONENT_DESTRUCTOR_OP, + VM_RESOLVE_CURRIED_COMPONENT_OP, + VM_RESOLVE_DYNAMIC_COMPONENT_OP, + VM_ROOT_SCOPE_OP, + VM_SET_BLOCK_OP, + VM_SET_BLOCKS_OP, + VM_SET_NAMED_VARIABLES_OP, + VM_SET_VARIABLE_OP, + VM_SETUP_FOR_EVAL_OP, + VM_VIRTUAL_ROOT_SCOPE_OP, +} from '@glimmer/constants'; import { unwrap } from '@glimmer/debug-util'; import { hasCapability } from '@glimmer/manager'; import { EMPTY_STRING_ARRAY, reverse } from '@glimmer/util'; -import { $s0, $s1, $sp, InternalComponentCapabilities, MachineOp, Op } from '@glimmer/vm'; +import { $s0, $s1, $sp, InternalComponentCapabilities } from '@glimmer/vm'; import type { PushExpressionOp, PushStatementOp } from '../../syntax/compilers'; @@ -74,7 +120,7 @@ export function InvokeComponent( let blocks = Array.isArray(_blocks) || _blocks === null ? namedBlocks(_blocks) : _blocks; if (compilable) { - op(Op.PushComponentDefinition, handle); + op(VM_PUSH_COMPONENT_DEFINITION_OP, handle); InvokeStaticComponent(op, { capabilities: capabilities, layout: compilable, @@ -84,7 +130,7 @@ export function InvokeComponent( blocks, }); } else { - op(Op.PushComponentDefinition, handle); + op(VM_PUSH_COMPONENT_DEFINITION_OP, handle); InvokeNonStaticComponent(op, { capabilities: capabilities, elementBlock, @@ -116,20 +162,20 @@ export function InvokeDynamicComponent( () => { expr(op, definition); - op(Op.Dup, $sp, 0); + op(VM_DUP_OP, $sp, 0); return 2; }, () => { - op(Op.JumpUnless, labelOperand('ELSE')); + op(VM_JUMP_UNLESS_OP, labelOperand('ELSE')); if (curried) { - op(Op.ResolveCurriedComponent); + op(VM_RESOLVE_CURRIED_COMPONENT_OP); } else { - op(Op.ResolveDynamicComponent, isStrictMode()); + op(VM_RESOLVE_DYNAMIC_COMPONENT_OP, isStrictMode()); } - op(Op.PushDynamicComponentInstance); + op(VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP); InvokeNonStaticComponent(op, { capabilities: true, elementBlock, @@ -166,10 +212,10 @@ function InvokeStaticComponent( return; } - op(Op.Fetch, $s0); - op(Op.Dup, $sp, 1); - op(Op.Load, $s0); - op(MachineOp.PushFrame); + op(VM_FETCH_OP, $s0); + op(VM_DUP_OP, $sp, 1); + op(VM_LOAD_OP, $s0); + op(VM_PUSH_FRAME_OP); // Setup arguments let { symbols } = symbolTable; @@ -237,7 +283,7 @@ function InvokeStaticComponent( // Finally, push the VM arguments themselves. These args won't need access // to blocks (they aren't accessible from userland anyways), so we push an // empty array instead of the actual block names. - op(Op.PushArgs, names, EMPTY_STRING_ARRAY, flags); + op(VM_PUSH_ARGS_OP, names, EMPTY_STRING_ARRAY, flags); // And push an extra pop operation to remove the args before we begin setting // variables on the local context @@ -261,31 +307,31 @@ function InvokeStaticComponent( } } - op(Op.BeginComponentTransaction, $s0); + op(VM_BEGIN_COMPONENT_TRANSACTION_OP, $s0); if (hasCapability(capabilities, InternalComponentCapabilities.dynamicScope)) { - op(Op.PushDynamicScope); + op(VM_PUSH_DYNAMIC_SCOPE_OP); } if (hasCapability(capabilities, InternalComponentCapabilities.createInstance)) { // eslint-disable-next-line @typescript-eslint/no-explicit-any - op(Op.CreateComponent, (blocks.has('default') as any) | 0, $s0); + op(VM_CREATE_COMPONENT_OP, (blocks.has('default') as any) | 0, $s0); } - op(Op.RegisterComponentDestructor, $s0); + op(VM_REGISTER_COMPONENT_DESTRUCTOR_OP, $s0); if (hasCapability(capabilities, InternalComponentCapabilities.createArgs)) { - op(Op.GetComponentSelf, $s0); + op(VM_GET_COMPONENT_SELF_OP, $s0); } else { - op(Op.GetComponentSelf, $s0, argNames); + op(VM_GET_COMPONENT_SELF_OP, $s0, argNames); } // Setup the new root scope for the component - op(Op.RootScope, symbols.length + 1, Object.keys(blocks).length > 0 ? 1 : 0); + op(VM_ROOT_SCOPE_OP, symbols.length + 1, Object.keys(blocks).length > 0 ? 1 : 0); // Pop the self reference off the stack and set it to the symbol for `this` // in the new scope. This is why all subsequent symbols are increased by one. - op(Op.SetVariable, 0); + op(VM_SET_VARIABLE_OP, 0); // Going in reverse, now we pop the args/blocks off the stack, starting with // arguments, and assign them to their symbols in the new scope. @@ -296,36 +342,36 @@ function InvokeStaticComponent( if (symbol === -1) { // The expression was not bound to a local symbol, it was only pushed to be // used with VM args in the javascript side - op(Op.Pop, 1); + op(VM_POP_OP, 1); } else { - op(Op.SetVariable, symbol + 1); + op(VM_SET_VARIABLE_OP, symbol + 1); } } // if any positional params exist, pop them off the stack as well if (positional !== null) { - op(Op.Pop, positional.length); + op(VM_POP_OP, positional.length); } // Finish up by popping off and assigning blocks for (const symbol of reverse(blockSymbols)) { - op(Op.SetBlock, symbol + 1); + op(VM_SET_BLOCK_OP, symbol + 1); } - op(Op.Constant, layoutOperand(layout)); - op(Op.CompileBlock); - op(MachineOp.InvokeVirtual); - op(Op.DidRenderLayout, $s0); + op(VM_CONSTANT_OP, layoutOperand(layout)); + op(VM_COMPILE_BLOCK_OP); + op(VM_INVOKE_VIRTUAL_OP); + op(VM_DID_RENDER_LAYOUT_OP, $s0); - op(MachineOp.PopFrame); - op(Op.PopScope); + op(VM_POP_FRAME_OP); + op(VM_POP_SCOPE_OP); if (hasCapability(capabilities, InternalComponentCapabilities.dynamicScope)) { - op(Op.PopDynamicScope); + op(VM_POP_DYNAMIC_SCOPE_OP); } - op(Op.CommitComponentTransaction); - op(Op.Load, $s0); + op(VM_COMMIT_COMPONENT_TRANSACTION_OP); + op(VM_LOAD_OP, $s0); } export function InvokeNonStaticComponent( @@ -340,27 +386,27 @@ export function InvokeNonStaticComponent( let blocks = namedBlocks.with('attrs', elementBlock); - op(Op.Fetch, $s0); - op(Op.Dup, $sp, 1); - op(Op.Load, $s0); + op(VM_FETCH_OP, $s0); + op(VM_DUP_OP, $sp, 1); + op(VM_LOAD_OP, $s0); - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); CompileArgs(op, positional, named, blocks, atNames); - op(Op.PrepareArgs, $s0); + op(VM_PREPARE_ARGS_OP, $s0); invokePreparedComponent(op, blocks.has('default'), bindableBlocks, bindableAtNames, () => { if (layout) { - op(Op.PushSymbolTable, symbolTableOperand(layout.symbolTable)); - op(Op.Constant, layoutOperand(layout)); - op(Op.CompileBlock); + op(VM_PUSH_SYMBOL_TABLE_OP, symbolTableOperand(layout.symbolTable)); + op(VM_CONSTANT_OP, layoutOperand(layout)); + op(VM_COMPILE_BLOCK_OP); } else { - op(Op.GetComponentLayout, $s0); + op(VM_GET_COMPONENT_LAYOUT_OP, $s0); } - op(Op.PopulateLayout, $s0); + op(VM_POPULATE_LAYOUT_OP, $s0); }); - op(Op.Load, $s0); + op(VM_LOAD_OP, $s0); } export function WrappedComponent( @@ -370,24 +416,24 @@ export function WrappedComponent( ): void { op(HighLevelBuilderOpcodes.StartLabels); WithSavedRegister(op, $s1, () => { - op(Op.GetComponentTagName, $s0); - op(Op.PrimitiveReference); - op(Op.Dup, $sp, 0); + op(VM_GET_COMPONENT_TAG_NAME_OP, $s0); + op(VM_PRIMITIVE_REFERENCE_OP); + op(VM_DUP_OP, $sp, 0); }); - op(Op.JumpUnless, labelOperand('BODY')); - op(Op.Fetch, $s1); - op(Op.PutComponentOperations); - op(Op.OpenDynamicElement); - op(Op.DidCreateElement, $s0); + op(VM_JUMP_UNLESS_OP, labelOperand('BODY')); + op(VM_FETCH_OP, $s1); + op(VM_PUT_COMPONENT_OPERATIONS_OP); + op(VM_OPEN_DYNAMIC_ELEMENT_OP); + op(VM_DID_CREATE_ELEMENT_OP, $s0); YieldBlock(op, attrsBlockNumber, null); - op(Op.FlushElement); + op(VM_FLUSH_ELEMENT_OP); op(HighLevelBuilderOpcodes.Label, 'BODY'); InvokeStaticBlock(op, [layout.block[0], []]); - op(Op.Fetch, $s1); - op(Op.JumpUnless, labelOperand('END')); - op(Op.CloseElement); + op(VM_FETCH_OP, $s1); + op(VM_JUMP_UNLESS_OP, labelOperand('END')); + op(VM_CLOSE_ELEMENT_OP); op(HighLevelBuilderOpcodes.Label, 'END'); - op(Op.Load, $s1); + op(VM_LOAD_OP, $s1); op(HighLevelBuilderOpcodes.StopLabels); } @@ -398,11 +444,11 @@ export function invokePreparedComponent( bindableAtNames: boolean, populateLayout: Nullable<() => void> = null ): void { - op(Op.BeginComponentTransaction, $s0); - op(Op.PushDynamicScope); + op(VM_BEGIN_COMPONENT_TRANSACTION_OP, $s0); + op(VM_PUSH_DYNAMIC_SCOPE_OP); // eslint-disable-next-line @typescript-eslint/no-explicit-any - op(Op.CreateComponent, (hasBlock as any) | 0, $s0); + op(VM_CREATE_COMPONENT_OP, (hasBlock as any) | 0, $s0); // this has to run after createComponent to allow // for late-bound layouts, but a caller is free @@ -412,39 +458,39 @@ export function invokePreparedComponent( populateLayout(); } - op(Op.RegisterComponentDestructor, $s0); - op(Op.GetComponentSelf, $s0); + op(VM_REGISTER_COMPONENT_DESTRUCTOR_OP, $s0); + op(VM_GET_COMPONENT_SELF_OP, $s0); - op(Op.VirtualRootScope, $s0); - op(Op.SetVariable, 0); - op(Op.SetupForEval, $s0); + op(VM_VIRTUAL_ROOT_SCOPE_OP, $s0); + op(VM_SET_VARIABLE_OP, 0); + op(VM_SETUP_FOR_EVAL_OP, $s0); - if (bindableAtNames) op(Op.SetNamedVariables, $s0); - if (bindableBlocks) op(Op.SetBlocks, $s0); + if (bindableAtNames) op(VM_SET_NAMED_VARIABLES_OP, $s0); + if (bindableBlocks) op(VM_SET_BLOCKS_OP, $s0); - op(Op.Pop, 1); - op(Op.InvokeComponentLayout, $s0); - op(Op.DidRenderLayout, $s0); - op(MachineOp.PopFrame); + op(VM_POP_OP, 1); + op(VM_INVOKE_COMPONENT_LAYOUT_OP, $s0); + op(VM_DID_RENDER_LAYOUT_OP, $s0); + op(VM_POP_FRAME_OP); - op(Op.PopScope); - op(Op.PopDynamicScope); - op(Op.CommitComponentTransaction); + op(VM_POP_SCOPE_OP); + op(VM_POP_DYNAMIC_SCOPE_OP); + op(VM_COMMIT_COMPONENT_TRANSACTION_OP); } export function InvokeBareComponent(op: PushStatementOp): void { - op(Op.Fetch, $s0); - op(Op.Dup, $sp, 1); - op(Op.Load, $s0); + op(VM_FETCH_OP, $s0); + op(VM_DUP_OP, $sp, 1); + op(VM_LOAD_OP, $s0); - op(MachineOp.PushFrame); - op(Op.PushEmptyArgs); - op(Op.PrepareArgs, $s0); + op(VM_PUSH_FRAME_OP); + op(VM_PUSH_EMPTY_ARGS_OP); + op(VM_PREPARE_ARGS_OP, $s0); invokePreparedComponent(op, false, false, true, () => { - op(Op.GetComponentLayout, $s0); - op(Op.PopulateLayout, $s0); + op(VM_GET_COMPONENT_LAYOUT_OP, $s0); + op(VM_POPULATE_LAYOUT_OP, $s0); }); - op(Op.Load, $s0); + op(VM_LOAD_OP, $s0); } export function WithSavedRegister( @@ -452,7 +498,7 @@ export function WithSavedRegister( register: SavedRegister, block: () => void ): void { - op(Op.Fetch, register); + op(VM_FETCH_OP, register); block(); - op(Op.Load, register); + op(VM_LOAD_OP, register); } diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/conditional.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/conditional.ts index d7dc06c185..72c4cefcdf 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/conditional.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/conditional.ts @@ -1,5 +1,16 @@ +import { + VM_ENTER_OP, + VM_EXIT_OP, + VM_JUMP_EQ_OP, + VM_JUMP_OP, + VM_JUMP_UNLESS_OP, + VM_POP_FRAME_OP, + VM_POP_OP, + VM_PUSH_FRAME_OP, + VM_RETURN_OP, + VM_RETURN_TO_OP, +} from '@glimmer/constants'; import { unwrap } from '@glimmer/debug-util'; -import { MachineOp, Op } from '@glimmer/vm'; import type { PushStatementOp } from '../../syntax/compilers'; @@ -26,14 +37,14 @@ export function SwitchCases( matcher(when); // Emit the opcodes for the switch - op(Op.Enter, 1); + op(VM_ENTER_OP, 1); bootstrap(); op(HighLevelBuilderOpcodes.StartLabels); // First, emit the jump opcodes. We don't need a jump for the last // opcode, since it bleeds directly into its clause. for (let clause of clauses.slice(0, -1)) { - op(Op.JumpEq, labelOperand(clause.label), clause.match); + op(VM_JUMP_EQ_OP, labelOperand(clause.label), clause.match); } // Enumerate the clauses in reverse order. Earlier matches will @@ -42,19 +53,19 @@ export function SwitchCases( let clause = unwrap(clauses[i]); op(HighLevelBuilderOpcodes.Label, clause.label); - op(Op.Pop, 1); + op(VM_POP_OP, 1); clause.callback(); // The first match is special: it is placed directly before the END // label, so no additional jump is needed at the end of it. if (i !== 0) { - op(MachineOp.Jump, labelOperand('END')); + op(VM_JUMP_OP, labelOperand('END')); } } op(HighLevelBuilderOpcodes.Label, 'END'); op(HighLevelBuilderOpcodes.StopLabels); - op(Op.Exit); + op(VM_EXIT_OP); } /** @@ -123,11 +134,11 @@ export function Replayable(op: PushStatementOp, args: () => number, body: () => // a unique meaning. op(HighLevelBuilderOpcodes.StartLabels); - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); // If the body invokes a block, its return will return to // END. Otherwise, the return in RETURN will return to END. - op(MachineOp.ReturnTo, labelOperand('ENDINITIAL')); + op(VM_RETURN_TO_OP, labelOperand('ENDINITIAL')); // Push the arguments onto the stack. The args() function // tells us how many stack elements to retain for re-execution @@ -144,7 +155,7 @@ export function Replayable(op: PushStatementOp, args: () => number, body: () => // in an #if), the DOM is cleared and the program is re-executed, // restoring `count` elements to the stack and executing the // instructions between the enter and exit. - op(Op.Enter, count); + op(VM_ENTER_OP, count); // Evaluate the body of the block. The body of the block may // return, which will jump execution to END during initial @@ -157,17 +168,17 @@ export function Replayable(op: PushStatementOp, args: () => number, body: () => op(HighLevelBuilderOpcodes.Label, 'FINALLY'); // Finalize the DOM. - op(Op.Exit); + op(VM_EXIT_OP); // In initial execution, this is a noop: it returns to the // immediately following opcode. In updating execution, this // exits the updating routine. - op(MachineOp.Return); + op(VM_RETURN_OP); // Cleanup code for the block. Runs on initial execution // but not on updating. op(HighLevelBuilderOpcodes.Label, 'ENDINITIAL'); - op(MachineOp.PopFrame); + op(VM_POP_FRAME_OP); op(HighLevelBuilderOpcodes.StopLabels); } @@ -194,13 +205,13 @@ export function ReplayableIf( ): void { return Replayable(op, args, () => { // If the conditional is false, jump to the ELSE label. - op(Op.JumpUnless, labelOperand('ELSE')); + op(VM_JUMP_UNLESS_OP, labelOperand('ELSE')); // Otherwise, execute the code associated with the true branch. ifTrue(); // We're done, so return. In the initial execution, this runs // the cleanup code. In the updating VM, it exits the updating // routine. - op(MachineOp.Jump, labelOperand('FINALLY')); + op(VM_JUMP_OP, labelOperand('FINALLY')); op(HighLevelBuilderOpcodes.Label, 'ELSE'); // If the conditional is false, and code associatied ith the diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/expr.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/expr.ts index 027b6a4e2a..53a689ebb9 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/expr.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/expr.ts @@ -1,5 +1,5 @@ import type { WireFormat } from '@glimmer/interfaces'; -import { Op } from '@glimmer/vm'; +import { VM_PRIMITIVE_REFERENCE_OP } from '@glimmer/constants'; import type { PushExpressionOp } from '../../syntax/compilers'; @@ -11,6 +11,6 @@ export function expr(op: PushExpressionOp, expression: WireFormat.Expression): v EXPRESSIONS.compile(op, expression); } else { PushPrimitive(op, expression); - op(Op.PrimitiveReference); + op(VM_PRIMITIVE_REFERENCE_OP); } } diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/shared.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/shared.ts index 5479748eaf..1526dad5ab 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/shared.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/shared.ts @@ -5,8 +5,8 @@ import type { Nullable, WireFormat, } from '@glimmer/interfaces'; +import { VM_PUSH_ARGS_OP, VM_PUSH_EMPTY_ARGS_OP } from '@glimmer/constants'; import { EMPTY_ARRAY, EMPTY_STRING_ARRAY } from '@glimmer/util'; -import { Op } from '@glimmer/vm'; import type { PushExpressionOp, PushStatementOp } from '../../syntax/compilers'; @@ -53,7 +53,7 @@ export function CompileArgs( } } - op(Op.PushArgs, names as string[], blockNames, flags); + op(VM_PUSH_ARGS_OP, names as string[], blockNames, flags); } export function SimpleArgs( @@ -63,7 +63,7 @@ export function SimpleArgs( atNames: boolean ): void { if (positional === null && named === null) { - op(Op.PushEmptyArgs); + op(VM_PUSH_EMPTY_ARGS_OP); return; } @@ -83,7 +83,7 @@ export function SimpleArgs( } } - op(Op.PushArgs, names, EMPTY_STRING_ARRAY, flags); + op(VM_PUSH_ARGS_OP, names, EMPTY_STRING_ARRAY, flags); } /** diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/stdlib.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/stdlib.ts index 7c7a98e79e..ce11df4eba 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/stdlib.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/stdlib.ts @@ -4,7 +4,20 @@ import type { ContainingMetadata, HighLevelOp, } from '@glimmer/interfaces'; -import { $s0, ContentType, MachineOp, Op } from '@glimmer/vm'; +import { + VM_APPEND_DOCUMENT_FRAGMENT_OP, + VM_APPEND_HTML_OP, + VM_APPEND_NODE_OP, + VM_APPEND_SAFE_HTML_OP, + VM_APPEND_TEXT_OP, + VM_ASSERT_SAME_OP, + VM_CONTENT_TYPE_OP, + VM_INVOKE_STATIC_OP, + VM_MAIN_OP, + VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP, + VM_RESOLVE_CURRIED_COMPONENT_OP, +} from '@glimmer/constants'; +import { $s0, ContentType } from '@glimmer/vm'; import type { HighLevelStatementOp, PushStatementOp } from '../../syntax/compilers'; @@ -15,7 +28,7 @@ import { SwitchCases } from './conditional'; import { CallDynamic } from './vm'; export function main(op: PushStatementOp): void { - op(Op.Main, $s0); + op(VM_MAIN_OP, $s0); invokePreparedComponent(op, false, false, true); } @@ -34,54 +47,54 @@ export function StdAppend( ): void { SwitchCases( op, - () => op(Op.ContentType), + () => op(VM_CONTENT_TYPE_OP), (when) => { when(ContentType.String, () => { if (trusting) { - op(Op.AssertSame); - op(Op.AppendHTML); + op(VM_ASSERT_SAME_OP); + op(VM_APPEND_HTML_OP); } else { - op(Op.AppendText); + op(VM_APPEND_TEXT_OP); } }); if (typeof nonDynamicAppend === 'number') { when(ContentType.Component, () => { - op(Op.ResolveCurriedComponent); - op(Op.PushDynamicComponentInstance); + op(VM_RESOLVE_CURRIED_COMPONENT_OP); + op(VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP); InvokeBareComponent(op); }); when(ContentType.Helper, () => { CallDynamic(op, null, null, () => { - op(MachineOp.InvokeStatic, nonDynamicAppend); + op(VM_INVOKE_STATIC_OP, nonDynamicAppend); }); }); } else { // when non-dynamic, we can no longer call the value (potentially because we've already called it) // this prevents infinite loops. We instead coerce the value, whatever it is, into the DOM. when(ContentType.Component, () => { - op(Op.AppendText); + op(VM_APPEND_TEXT_OP); }); when(ContentType.Helper, () => { - op(Op.AppendText); + op(VM_APPEND_TEXT_OP); }); } when(ContentType.SafeString, () => { - op(Op.AssertSame); - op(Op.AppendSafeHTML); + op(VM_ASSERT_SAME_OP); + op(VM_APPEND_SAFE_HTML_OP); }); when(ContentType.Fragment, () => { - op(Op.AssertSame); - op(Op.AppendDocumentFragment); + op(VM_ASSERT_SAME_OP); + op(VM_APPEND_DOCUMENT_FRAGMENT_OP); }); when(ContentType.Node, () => { - op(Op.AssertSame); - op(Op.AppendNode); + op(VM_ASSERT_SAME_OP); + op(VM_APPEND_NODE_OP); }); } ); diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/vm.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/vm.ts index 48188e8473..652481fa5a 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/vm.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/helpers/vm.ts @@ -1,6 +1,23 @@ import type { CurriedType, NonSmallIntOperand, Nullable, WireFormat } from '@glimmer/interfaces'; -import { encodeImmediate, isSmallInt } from '@glimmer/util'; -import { $fp, $v0, MachineOp, Op } from '@glimmer/vm'; +import { + encodeImmediate, + isSmallInt, + VM_BIND_DYNAMIC_SCOPE_OP, + VM_CAPTURE_ARGS_OP, + VM_CURRY_OP, + VM_DUP_OP, + VM_DYNAMIC_HELPER_OP, + VM_FETCH_OP, + VM_HELPER_OP, + VM_POP_DYNAMIC_SCOPE_OP, + VM_POP_FRAME_OP, + VM_POP_OP, + VM_PRIMITIVE_OP, + VM_PRIMITIVE_REFERENCE_OP, + VM_PUSH_DYNAMIC_SCOPE_OP, + VM_PUSH_FRAME_OP, +} from '@glimmer/constants'; +import { $fp, $v0 } from '@glimmer/vm'; import type { PushExpressionOp, PushStatementOp } from '../../syntax/compilers'; @@ -22,7 +39,7 @@ export interface CompileHelper { */ export function PushPrimitiveReference(op: PushExpressionOp, value: Primitive): void { PushPrimitive(op, value); - op(Op.PrimitiveReference); + op(VM_PRIMITIVE_REFERENCE_OP); } /** @@ -37,7 +54,7 @@ export function PushPrimitive(op: PushExpressionOp, primitive: Primitive): void p = isSmallInt(p) ? encodeImmediate(p) : nonSmallIntOperand(p); } - op(Op.Primitive, p); + op(VM_PRIMITIVE_OP, p); } /** @@ -54,11 +71,11 @@ export function Call( positional: WireFormat.Core.Params, named: WireFormat.Core.Hash ): void { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); SimpleArgs(op, positional, named, false); - op(Op.Helper, handle); - op(MachineOp.PopFrame); - op(Op.Fetch, $v0); + op(VM_HELPER_OP, handle); + op(VM_POP_FRAME_OP); + op(VM_FETCH_OP, $v0); } /** @@ -74,19 +91,19 @@ export function CallDynamic( named: WireFormat.Core.Hash, append?: () => void ): void { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); SimpleArgs(op, positional, named, false); - op(Op.Dup, $fp, 1); - op(Op.DynamicHelper); + op(VM_DUP_OP, $fp, 1); + op(VM_DYNAMIC_HELPER_OP); if (append) { - op(Op.Fetch, $v0); + op(VM_FETCH_OP, $v0); append(); - op(MachineOp.PopFrame); - op(Op.Pop, 1); + op(VM_POP_FRAME_OP); + op(VM_POP_OP, 1); } else { - op(MachineOp.PopFrame); - op(Op.Pop, 1); - op(Op.Fetch, $v0); + op(VM_POP_FRAME_OP); + op(VM_POP_OP, 1); + op(VM_FETCH_OP, $v0); } } @@ -99,10 +116,10 @@ export function CallDynamic( * @param block a function that returns a list of statements to evaluate */ export function DynamicScope(op: PushStatementOp, names: string[], block: () => void): void { - op(Op.PushDynamicScope); - op(Op.BindDynamicScope, names); + op(VM_PUSH_DYNAMIC_SCOPE_OP); + op(VM_BIND_DYNAMIC_SCOPE_OP, names); block(); - op(Op.PopDynamicScope); + op(VM_POP_DYNAMIC_SCOPE_OP); } export function Curry( @@ -112,11 +129,11 @@ export function Curry( positional: WireFormat.Core.Params, named: WireFormat.Core.Hash ): void { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); SimpleArgs(op, positional, named, false); - op(Op.CaptureArgs); + op(VM_CAPTURE_ARGS_OP); expr(op, definition); - op(Op.Curry, type, isStrictMode()); - op(MachineOp.PopFrame); - op(Op.Fetch, $v0); + op(VM_CURRY_OP, type, isStrictMode()); + op(VM_POP_FRAME_OP); + op(VM_FETCH_OP, $v0); } diff --git a/packages/@glimmer/opcode-compiler/lib/opcode-builder/operands.ts b/packages/@glimmer/opcode-compiler/lib/opcode-builder/operands.ts index 9b19df1a52..a21481c552 100644 --- a/packages/@glimmer/opcode-compiler/lib/opcode-builder/operands.ts +++ b/packages/@glimmer/opcode-compiler/lib/opcode-builder/operands.ts @@ -20,8 +20,8 @@ import type { SymbolTableOperand, SymbolTableOperandType, } from '@glimmer/interfaces'; +import { isSmallInt } from '@glimmer/constants'; import { assert } from '@glimmer/debug-util'; -import { isSmallInt } from '@glimmer/util'; export const HighLevelOperands = { Label: 1 satisfies LabelOperandType, diff --git a/packages/@glimmer/opcode-compiler/lib/syntax/expressions.ts b/packages/@glimmer/opcode-compiler/lib/syntax/expressions.ts index 1cf3e675af..3841d39b89 100644 --- a/packages/@glimmer/opcode-compiler/lib/syntax/expressions.ts +++ b/packages/@glimmer/opcode-compiler/lib/syntax/expressions.ts @@ -1,5 +1,22 @@ import type { ExpressionSexpOpcode } from '@glimmer/interfaces'; -import { $v0, MachineOp, Op } from '@glimmer/vm'; +import { + VM_COMPILE_BLOCK_OP, + VM_CONCAT_OP, + VM_CONSTANT_REFERENCE_OP, + VM_FETCH_OP, + VM_GET_DYNAMIC_VAR_OP, + VM_GET_PROPERTY_OP, + VM_GET_VARIABLE_OP, + VM_HAS_BLOCK_OP, + VM_HAS_BLOCK_PARAMS_OP, + VM_IF_INLINE_OP, + VM_LOG_OP, + VM_NOT_OP, + VM_POP_FRAME_OP, + VM_PUSH_FRAME_OP, + VM_SPREAD_BLOCK_OP, +} from '@glimmer/constants'; +import { $v0 } from '@glimmer/vm'; import { SexpOpcodes } from '@glimmer/wire-format'; import type { PushExpressionOp } from './compilers'; @@ -18,7 +35,7 @@ EXPRESSIONS.add(SexpOpcodes.Concat, (op, [, parts]) => { expr(op, part); } - op(Op.Concat, parts.length); + op(VM_CONCAT_OP, parts.length); }); EXPRESSIONS.add(SexpOpcodes.Call, (op, [, expression, positional, named]) => { @@ -37,13 +54,13 @@ EXPRESSIONS.add(SexpOpcodes.Curry, (op, [, expr, type, positional, named]) => { }); EXPRESSIONS.add(SexpOpcodes.GetSymbol, (op, [, sym, path]) => { - op(Op.GetVariable, sym); + op(VM_GET_VARIABLE_OP, sym); withPath(op, path); }); EXPRESSIONS.add(SexpOpcodes.GetLexicalSymbol, (op, [, sym, path]) => { op(HighLevelResolutionOpcodes.TemplateLocal, sym, (handle: number) => { - op(Op.ConstantReference, handle); + op(VM_CONSTANT_REFERENCE_OP, handle); withPath(op, path); }); }); @@ -68,21 +85,21 @@ function withPath(op: PushExpressionOp, path?: string[]) { if (path === undefined || path.length === 0) return; for (let i = 0; i < path.length; i++) { - op(Op.GetProperty, path[i]); + op(VM_GET_PROPERTY_OP, path[i]); } } EXPRESSIONS.add(SexpOpcodes.Undefined, (op) => PushPrimitiveReference(op, undefined)); EXPRESSIONS.add(SexpOpcodes.HasBlock, (op, [, block]) => { expr(op, block); - op(Op.HasBlock); + op(VM_HAS_BLOCK_OP); }); EXPRESSIONS.add(SexpOpcodes.HasBlockParams, (op, [, block]) => { expr(op, block); - op(Op.SpreadBlock); - op(Op.CompileBlock); - op(Op.HasBlockParams); + op(VM_SPREAD_BLOCK_OP); + op(VM_COMPILE_BLOCK_OP); + op(VM_HAS_BLOCK_PARAMS_OP); }); EXPRESSIONS.add(SexpOpcodes.IfInline, (op, [, condition, truthy, falsy]) => { @@ -90,23 +107,23 @@ EXPRESSIONS.add(SexpOpcodes.IfInline, (op, [, condition, truthy, falsy]) => { expr(op, falsy); expr(op, truthy); expr(op, condition); - op(Op.IfInline); + op(VM_IF_INLINE_OP); }); EXPRESSIONS.add(SexpOpcodes.Not, (op, [, value]) => { expr(op, value); - op(Op.Not); + op(VM_NOT_OP); }); EXPRESSIONS.add(SexpOpcodes.GetDynamicVar, (op, [, expression]) => { expr(op, expression); - op(Op.GetDynamicVar); + op(VM_GET_DYNAMIC_VAR_OP); }); EXPRESSIONS.add(SexpOpcodes.Log, (op, [, positional]) => { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); SimpleArgs(op, positional, null, false); - op(Op.Log); - op(MachineOp.PopFrame); - op(Op.Fetch, $v0); + op(VM_LOG_OP); + op(VM_POP_FRAME_OP); + op(VM_FETCH_OP, $v0); }); diff --git a/packages/@glimmer/opcode-compiler/lib/syntax/statements.ts b/packages/@glimmer/opcode-compiler/lib/syntax/statements.ts index 7228aa61fb..f5d6b45824 100644 --- a/packages/@glimmer/opcode-compiler/lib/syntax/statements.ts +++ b/packages/@glimmer/opcode-compiler/lib/syntax/statements.ts @@ -5,7 +5,39 @@ import type { WellKnownTagName, WireFormat, } from '@glimmer/interfaces'; -import { $fp, $sp, ContentType, MachineOp, Op } from '@glimmer/vm'; +import { + VM_CLOSE_ELEMENT_OP, + VM_COMMENT_OP, + VM_COMPONENT_ATTR_OP, + VM_CONSTANT_REFERENCE_OP, + VM_DEBUGGER_OP, + VM_DUP_OP, + VM_DYNAMIC_ATTR_OP, + VM_DYNAMIC_CONTENT_TYPE_OP, + VM_DYNAMIC_MODIFIER_OP, + VM_ENTER_LIST_OP, + VM_EXIT_LIST_OP, + VM_FLUSH_ELEMENT_OP, + VM_INVOKE_STATIC_OP, + VM_ITERATE_OP, + VM_JUMP_OP, + VM_MODIFIER_OP, + VM_OPEN_ELEMENT_OP, + VM_POP_FRAME_OP, + VM_POP_OP, + VM_POP_REMOTE_ELEMENT_OP, + VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP, + VM_PUSH_FRAME_OP, + VM_PUSH_REMOTE_ELEMENT_OP, + VM_PUT_COMPONENT_OPERATIONS_OP, + VM_RESOLVE_CURRIED_COMPONENT_OP, + VM_RETURN_TO_OP, + VM_STATIC_ATTR_OP, + VM_STATIC_COMPONENT_ATTR_OP, + VM_TEXT_OP, + VM_TO_BOOLEAN_OP, +} from '@glimmer/constants'; +import { $fp, $sp, ContentType } from '@glimmer/vm'; import { SexpOpcodes } from '@glimmer/wire-format'; import type { PushStatementOp } from './compilers'; @@ -56,63 +88,63 @@ export function inflateAttrName(attrName: string | WellKnownAttrName): string { return typeof attrName === 'string' ? attrName : INFLATE_ATTR_TABLE[attrName]; } -STATEMENTS.add(SexpOpcodes.Comment, (op, sexp) => op(Op.Comment, sexp[1])); -STATEMENTS.add(SexpOpcodes.CloseElement, (op) => op(Op.CloseElement)); -STATEMENTS.add(SexpOpcodes.FlushElement, (op) => op(Op.FlushElement)); +STATEMENTS.add(SexpOpcodes.Comment, (op, sexp) => op(VM_COMMENT_OP, sexp[1])); +STATEMENTS.add(SexpOpcodes.CloseElement, (op) => op(VM_CLOSE_ELEMENT_OP)); +STATEMENTS.add(SexpOpcodes.FlushElement, (op) => op(VM_FLUSH_ELEMENT_OP)); STATEMENTS.add(SexpOpcodes.Modifier, (op, [, expression, positional, named]) => { if (isGetFreeModifier(expression)) { op(HighLevelResolutionOpcodes.Modifier, expression, (handle: number) => { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); SimpleArgs(op, positional, named, false); - op(Op.Modifier, handle); - op(MachineOp.PopFrame); + op(VM_MODIFIER_OP, handle); + op(VM_POP_FRAME_OP); }); } else { expr(op, expression); - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); SimpleArgs(op, positional, named, false); - op(Op.Dup, $fp, 1); - op(Op.DynamicModifier); - op(MachineOp.PopFrame); + op(VM_DUP_OP, $fp, 1); + op(VM_DYNAMIC_MODIFIER_OP); + op(VM_POP_FRAME_OP); } }); STATEMENTS.add(SexpOpcodes.StaticAttr, (op, [, name, value, namespace]) => { - op(Op.StaticAttr, inflateAttrName(name), value as string, namespace ?? null); + op(VM_STATIC_ATTR_OP, inflateAttrName(name), value as string, namespace ?? null); }); STATEMENTS.add(SexpOpcodes.StaticComponentAttr, (op, [, name, value, namespace]) => { - op(Op.StaticComponentAttr, inflateAttrName(name), value as string, namespace ?? null); + op(VM_STATIC_COMPONENT_ATTR_OP, inflateAttrName(name), value as string, namespace ?? null); }); STATEMENTS.add(SexpOpcodes.DynamicAttr, (op, [, name, value, namespace]) => { expr(op, value); - op(Op.DynamicAttr, inflateAttrName(name), false, namespace ?? null); + op(VM_DYNAMIC_ATTR_OP, inflateAttrName(name), false, namespace ?? null); }); STATEMENTS.add(SexpOpcodes.TrustingDynamicAttr, (op, [, name, value, namespace]) => { expr(op, value); - op(Op.DynamicAttr, inflateAttrName(name), true, namespace ?? null); + op(VM_DYNAMIC_ATTR_OP, inflateAttrName(name), true, namespace ?? null); }); STATEMENTS.add(SexpOpcodes.ComponentAttr, (op, [, name, value, namespace]) => { expr(op, value); - op(Op.ComponentAttr, inflateAttrName(name), false, namespace ?? null); + op(VM_COMPONENT_ATTR_OP, inflateAttrName(name), false, namespace ?? null); }); STATEMENTS.add(SexpOpcodes.TrustingComponentAttr, (op, [, name, value, namespace]) => { expr(op, value); - op(Op.ComponentAttr, inflateAttrName(name), true, namespace ?? null); + op(VM_COMPONENT_ATTR_OP, inflateAttrName(name), true, namespace ?? null); }); STATEMENTS.add(SexpOpcodes.OpenElement, (op, [, tag]) => { - op(Op.OpenElement, inflateTagName(tag)); + op(VM_OPEN_ELEMENT_OP, inflateTagName(tag)); }); STATEMENTS.add(SexpOpcodes.OpenElementWithSplat, (op, [, tag]) => { - op(Op.PutComponentOperations); - op(Op.OpenElement, inflateTagName(tag)); + op(VM_PUT_COMPONENT_OPERATIONS_OP); + op(VM_OPEN_ELEMENT_OP, inflateTagName(tag)); }); STATEMENTS.add(SexpOpcodes.Component, (op, [, expr, elementBlock, named, blocks]) => { @@ -132,13 +164,13 @@ STATEMENTS.add(SexpOpcodes.Yield, (op, [, to, params]) => YieldBlock(op, to, par STATEMENTS.add(SexpOpcodes.AttrSplat, (op, [, to]) => YieldBlock(op, to, null)); STATEMENTS.add(SexpOpcodes.Debugger, (op, [, debugInfo]) => - op(Op.Debugger, debugSymbolsOperand(), debugInfo) + op(VM_DEBUGGER_OP, debugSymbolsOperand(), debugInfo) ); STATEMENTS.add(SexpOpcodes.Append, (op, [, value]) => { // Special case for static values if (!Array.isArray(value)) { - op(Op.Text, value === null || value === undefined ? '' : String(value)); + op(VM_TEXT_OP, value === null || value === undefined ? '' : String(value)); } else if (isGetFreeComponentOrHelper(value)) { op(HighLevelResolutionOpcodes.OptionalComponentOrHelper, value, { ifComponent(component: CompileTimeComponent) { @@ -146,17 +178,17 @@ STATEMENTS.add(SexpOpcodes.Append, (op, [, value]) => { }, ifHelper(handle: number) { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); Call(op, handle, null, null); - op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append')); - op(MachineOp.PopFrame); + op(VM_INVOKE_STATIC_OP, stdlibOperand('cautious-non-dynamic-append')); + op(VM_POP_FRAME_OP); }, ifValue(handle: number) { - op(MachineOp.PushFrame); - op(Op.ConstantReference, handle); - op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append')); - op(MachineOp.PopFrame); + op(VM_PUSH_FRAME_OP); + op(VM_CONSTANT_REFERENCE_OP, handle); + op(VM_INVOKE_STATIC_OP, stdlibOperand('cautious-non-dynamic-append')); + op(VM_POP_FRAME_OP); }, }); } else if (value[0] === SexpOpcodes.Call) { @@ -168,10 +200,10 @@ STATEMENTS.add(SexpOpcodes.Append, (op, [, value]) => { InvokeComponent(op, component, null, positional, hashToArgs(named), null); }, ifHelper(handle: number) { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); Call(op, handle, positional, named); - op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append')); - op(MachineOp.PopFrame); + op(VM_INVOKE_STATIC_OP, stdlibOperand('cautious-non-dynamic-append')); + op(VM_POP_FRAME_OP); }, }); } else { @@ -179,12 +211,12 @@ STATEMENTS.add(SexpOpcodes.Append, (op, [, value]) => { op, () => { expr(op, expression); - op(Op.DynamicContentType); + op(VM_DYNAMIC_CONTENT_TYPE_OP); }, (when) => { when(ContentType.Component, () => { - op(Op.ResolveCurriedComponent); - op(Op.PushDynamicComponentInstance); + op(VM_RESOLVE_CURRIED_COMPONENT_OP); + op(VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP); InvokeNonStaticComponent(op, { capabilities: true, elementBlock: null, @@ -197,28 +229,28 @@ STATEMENTS.add(SexpOpcodes.Append, (op, [, value]) => { when(ContentType.Helper, () => { CallDynamic(op, positional, named, () => { - op(MachineOp.InvokeStatic, stdlibOperand('cautious-non-dynamic-append')); + op(VM_INVOKE_STATIC_OP, stdlibOperand('cautious-non-dynamic-append')); }); }); } ); } } else { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); expr(op, value); - op(MachineOp.InvokeStatic, stdlibOperand('cautious-append')); - op(MachineOp.PopFrame); + op(VM_INVOKE_STATIC_OP, stdlibOperand('cautious-append')); + op(VM_POP_FRAME_OP); } }); STATEMENTS.add(SexpOpcodes.TrustingAppend, (op, [, value]) => { if (!Array.isArray(value)) { - op(Op.Text, value === null || value === undefined ? '' : String(value)); + op(VM_TEXT_OP, value === null || value === undefined ? '' : String(value)); } else { - op(MachineOp.PushFrame); + op(VM_PUSH_FRAME_OP); expr(op, value); - op(MachineOp.InvokeStatic, stdlibOperand('trusting-append')); - op(MachineOp.PopFrame); + op(VM_INVOKE_STATIC_OP, stdlibOperand('trusting-append')); + op(VM_POP_FRAME_OP); } }); @@ -246,15 +278,15 @@ STATEMENTS.add(SexpOpcodes.InElement, (op, [, block, guid, destination, insertBe } expr(op, destination); - op(Op.Dup, $sp, 0); + op(VM_DUP_OP, $sp, 0); return 4; }, () => { - op(Op.PushRemoteElement); + op(VM_PUSH_REMOTE_ELEMENT_OP); InvokeStaticBlock(op, block); - op(Op.PopRemoteElement); + op(VM_POP_REMOTE_ELEMENT_OP); } ); }); @@ -264,7 +296,7 @@ STATEMENTS.add(SexpOpcodes.If, (op, [, condition, block, inverse]) => op, () => { expr(op, condition); - op(Op.ToBoolean); + op(VM_TO_BOOLEAN_OP); return 1; }, @@ -298,20 +330,20 @@ STATEMENTS.add(SexpOpcodes.Each, (op, [, value, key, block, inverse]) => }, () => { - op(Op.EnterList, labelOperand('BODY'), labelOperand('ELSE')); - op(MachineOp.PushFrame); - op(Op.Dup, $fp, 1); - op(MachineOp.ReturnTo, labelOperand('ITER')); + op(VM_ENTER_LIST_OP, labelOperand('BODY'), labelOperand('ELSE')); + op(VM_PUSH_FRAME_OP); + op(VM_DUP_OP, $fp, 1); + op(VM_RETURN_TO_OP, labelOperand('ITER')); op(HighLevelBuilderOpcodes.Label, 'ITER'); - op(Op.Iterate, labelOperand('BREAK')); + op(VM_ITERATE_OP, labelOperand('BREAK')); op(HighLevelBuilderOpcodes.Label, 'BODY'); InvokeStaticBlockWithStack(op, block, 2); - op(Op.Pop, 2); - op(MachineOp.Jump, labelOperand('FINALLY')); + op(VM_POP_OP, 2); + op(VM_JUMP_OP, labelOperand('FINALLY')); op(HighLevelBuilderOpcodes.Label, 'BREAK'); - op(MachineOp.PopFrame); - op(Op.ExitList); - op(MachineOp.Jump, labelOperand('FINALLY')); + op(VM_POP_FRAME_OP); + op(VM_EXIT_LIST_OP); + op(VM_JUMP_OP, labelOperand('FINALLY')); op(HighLevelBuilderOpcodes.Label, 'ELSE'); if (inverse) { diff --git a/packages/@glimmer/opcode-compiler/lib/wrapped-component.ts b/packages/@glimmer/opcode-compiler/lib/wrapped-component.ts index 7f94a677a3..48a69d5794 100644 --- a/packages/@glimmer/opcode-compiler/lib/wrapped-component.ts +++ b/packages/@glimmer/opcode-compiler/lib/wrapped-component.ts @@ -8,7 +8,7 @@ import type { Nullable, ProgramSymbolTable, } from '@glimmer/interfaces'; -import { LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import type { HighLevelStatementOp } from './syntax/compilers'; @@ -71,7 +71,7 @@ export class WrappedBuilder implements CompilableProgram { this.compiled = handle; - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { debugCompiler(context, handle); } diff --git a/packages/@glimmer/opcode-compiler/package.json b/packages/@glimmer/opcode-compiler/package.json index e4d54e7b72..29ae2bffc0 100644 --- a/packages/@glimmer/opcode-compiler/package.json +++ b/packages/@glimmer/opcode-compiler/package.json @@ -50,6 +50,7 @@ }, "devDependencies": { "@glimmer-workspace/build-support": "workspace:*", + "@glimmer/constants": "workspace:*", "@glimmer/debug": "workspace:*", "@glimmer/debug-util": "workspace:*", "@glimmer/local-debug-flags": "workspace:*", diff --git a/packages/@glimmer/program/lib/constants.ts b/packages/@glimmer/program/lib/constants.ts index cac655ed41..a65f52fbd9 100644 --- a/packages/@glimmer/program/lib/constants.ts +++ b/packages/@glimmer/program/lib/constants.ts @@ -10,6 +10,7 @@ import type { RuntimeConstants, Template, } from '@glimmer/interfaces'; +import { constants } from '@glimmer/constants'; import { assert, expect, unwrapTemplate } from '@glimmer/debug-util'; import { capabilityFlagsFrom, @@ -20,7 +21,7 @@ import { managerHasCapability, } from '@glimmer/manager'; import { templateFactory } from '@glimmer/opcode-compiler'; -import { constants, enumerate } from '@glimmer/util'; +import { enumerate } from '@glimmer/util'; import { InternalComponentCapabilities } from '@glimmer/vm'; import { DEFAULT_TEMPLATE } from './util/default-template'; diff --git a/packages/@glimmer/program/lib/program.ts b/packages/@glimmer/program/lib/program.ts index af729a0aae..a8860aab9c 100644 --- a/packages/@glimmer/program/lib/program.ts +++ b/packages/@glimmer/program/lib/program.ts @@ -12,12 +12,12 @@ import { MACHINE_MASK } from '@glimmer/vm'; import { RuntimeOpImpl } from './opcode'; -const enum TableSlotState { - Allocated, - Freed, - Purged, - Pointer, -} +const ALLOCATED = 0; +const FREED = 1; +const PURGED = 2; +const POINTER = 3; + +type TableSlotState = typeof ALLOCATED | typeof FREED | typeof PURGED | typeof POINTER; export type Placeholder = [number, () => number]; export type StdlibPlaceholder = [number, StdLibOperand]; @@ -130,7 +130,7 @@ export class HeapImpl implements CompileTimeHeap, RuntimeHeap { // wrapped to prevent us from allocating extra space in prod. In the future, // if we start using the compact API, we should change this. if (LOCAL_DEBUG) { - this.handleState[handle] = TableSlotState.Allocated; + this.handleState[handle] = ALLOCATED; } } @@ -150,7 +150,7 @@ export class HeapImpl implements CompileTimeHeap, RuntimeHeap { } free(handle: number): void { - this.handleState[handle] = TableSlotState.Freed; + this.handleState[handle] = FREED; } /** @@ -169,21 +169,21 @@ export class HeapImpl implements CompileTimeHeap, RuntimeHeap { let size = unwrap(handleTable[i + 1]) - unwrap(offset); let state = handleState[i]; - if (state === TableSlotState.Purged) { + if (state === PURGED) { continue; - } else if (state === TableSlotState.Freed) { + } else if (state === FREED) { // transition to "already freed" aka "purged" // a good improvement would be to reuse // these slots - handleState[i] = TableSlotState.Purged; + handleState[i] = PURGED; compactedSize += size; - } else if (state === TableSlotState.Allocated) { + } else if (state === ALLOCATED) { for (let j = offset; j <= i + size; j++) { heap[j - compactedSize] = unwrap(heap[j]); } handleTable[i] = offset - compactedSize; - } else if (state === TableSlotState.Pointer) { + } else if (state === POINTER) { handleTable[i] = offset - compactedSize; } } diff --git a/packages/@glimmer/program/package.json b/packages/@glimmer/program/package.json index e48b5df0b3..8ba67eb9ca 100644 --- a/packages/@glimmer/program/package.json +++ b/packages/@glimmer/program/package.json @@ -38,7 +38,6 @@ "test:types": "tsc --noEmit -p ../tsconfig.json" }, "dependencies": { - "@glimmer/debug-util": "workspace:*", "@glimmer/encoder": "workspace:*", "@glimmer/env": "0.1.7", "@glimmer/interfaces": "workspace:*", @@ -50,6 +49,8 @@ }, "devDependencies": { "@glimmer-workspace/build-support": "workspace:*", + "@glimmer/constants": "workspace:*", + "@glimmer/debug-util": "workspace:*", "@glimmer/local-debug-flags": "workspace:*", "eslint": "^8.52.0", "publint": "^0.2.5", diff --git a/packages/@glimmer/runtime/lib/compat/svg-inner-html-fix.ts b/packages/@glimmer/runtime/lib/compat/svg-inner-html-fix.ts index e5f55b9d3b..c2157c1a95 100644 --- a/packages/@glimmer/runtime/lib/compat/svg-inner-html-fix.ts +++ b/packages/@glimmer/runtime/lib/compat/svg-inner-html-fix.ts @@ -5,20 +5,14 @@ import type { SimpleElement, SimpleNode, } from '@glimmer/interfaces'; +import { INSERT_AFTER_BEGIN, INSERT_BEFORE_END, NS_SVG } from '@glimmer/constants'; import { assert, castToBrowser, unwrap } from '@glimmer/debug-util'; -import { clearElement, INSERT_AFTER_BEGIN, INSERT_BEFORE_END, NS_SVG } from '@glimmer/util'; +import { clearElement } from '@glimmer/util'; import type { DOMOperations } from '../dom/operations'; import { moveNodesBefore } from '../dom/operations'; -export enum InsertPosition { - beforebegin = 'beforebegin', - afterbegin = 'afterbegin', - beforeend = 'beforeend', - afterend = 'afterend', -} - // Patch: insertAdjacentHTML on SVG Fix // Browsers: Safari, IE, Edge, Firefox ~33-34 // Reason: insertAdjacentHTML does not exist on SVG elements in Safari. It is diff --git a/packages/@glimmer/runtime/lib/compat/text-node-merging-fix.ts b/packages/@glimmer/runtime/lib/compat/text-node-merging-fix.ts index 3527be707a..53acc56815 100644 --- a/packages/@glimmer/runtime/lib/compat/text-node-merging-fix.ts +++ b/packages/@glimmer/runtime/lib/compat/text-node-merging-fix.ts @@ -6,7 +6,7 @@ import type { SimpleElement, SimpleNode, } from '@glimmer/interfaces'; -import { INSERT_BEFORE_END } from '@glimmer/util'; +import { INSERT_BEFORE_END } from '@glimmer/constants'; import type { DOMOperations } from '../dom/operations'; diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/-debug-strip.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/-debug-strip.ts index 4bad535c78..6f3744898c 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/-debug-strip.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/-debug-strip.ts @@ -24,9 +24,9 @@ import { CheckHandle, CheckInstanceof, CheckInterface, + CheckNullable, CheckNumber, CheckObject, - CheckOption, CheckOr, CheckProgramSymbolTable, CheckString, @@ -45,7 +45,7 @@ export const CheckTag: Checker = CheckInterface({ }); export const CheckOperations: Checker> = wrap(() => - CheckOption(CheckInstanceof(ComponentElementOperations)) + CheckNullable(CheckInstanceof(ComponentElementOperations)) ); class ReferenceChecker { @@ -142,7 +142,7 @@ export const CheckScopeBlock: Checker = CheckInterface({ }); export const CheckComponentDefinition: Checker = CheckInterface({ - resolvedName: CheckOption(CheckString), + resolvedName: CheckNullable(CheckString), handle: CheckNumber, state: CheckOr(CheckObject, CheckFunction), manager: CheckComponentManager, diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/component.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/component.ts index 708ad49079..f00c2fbd55 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/component.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/component.ts @@ -25,6 +25,35 @@ import type { WithUpdateHook, } from '@glimmer/interfaces'; import type { Reference } from '@glimmer/reference'; +import { + VM_BEGIN_COMPONENT_TRANSACTION_OP, + VM_CAPTURE_ARGS_OP, + VM_COMMIT_COMPONENT_TRANSACTION_OP, + VM_COMPONENT_ATTR_OP, + VM_CREATE_COMPONENT_OP, + VM_DID_CREATE_ELEMENT_OP, + VM_DID_RENDER_LAYOUT_OP, + VM_GET_COMPONENT_LAYOUT_OP, + VM_GET_COMPONENT_SELF_OP, + VM_GET_COMPONENT_TAG_NAME_OP, + VM_INVOKE_COMPONENT_LAYOUT_OP, + VM_MAIN_OP, + VM_POPULATE_LAYOUT_OP, + VM_PREPARE_ARGS_OP, + VM_PUSH_ARGS_OP, + VM_PUSH_COMPONENT_DEFINITION_OP, + VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP, + VM_PUSH_EMPTY_ARGS_OP, + VM_PUT_COMPONENT_OPERATIONS_OP, + VM_REGISTER_COMPONENT_DESTRUCTOR_OP, + VM_RESOLVE_CURRIED_COMPONENT_OP, + VM_RESOLVE_DYNAMIC_COMPONENT_OP, + VM_SET_BLOCKS_OP, + VM_SET_NAMED_VARIABLES_OP, + VM_SETUP_FOR_EVAL_OP, + VM_STATIC_COMPONENT_ATTR_OP, + VM_VIRTUAL_ROOT_SCOPE_OP, +} from '@glimmer/constants'; import { check, CheckFunction, @@ -33,6 +62,7 @@ import { CheckInterface, CheckOr, CheckProgramSymbolTable, + CheckRegister, CheckString, } from '@glimmer/debug'; import { assert, debugToString, expect, unwrap, unwrapTemplate } from '@glimmer/debug-util'; @@ -40,7 +70,7 @@ import { registerDestructor } from '@glimmer/destroyable'; import { managerHasCapability } from '@glimmer/manager'; import { isConstRef, valueForRef } from '@glimmer/reference'; import { assign, dict, EMPTY_STRING_ARRAY, enumerate } from '@glimmer/util'; -import { $t0, $t1, CurriedTypes, InternalComponentCapabilities, Op } from '@glimmer/vm'; +import { $t0, $t1, CurriedTypes, InternalComponentCapabilities } from '@glimmer/vm'; import type { CurriedValue } from '../../curried-value'; import type { UpdatingVM } from '../../vm'; @@ -101,7 +131,7 @@ export interface PartialComponentDefinition { manager: InternalComponentManager; } -APPEND_OPCODES.add(Op.PushComponentDefinition, (vm, { op1: handle }) => { +APPEND_OPCODES.add(VM_PUSH_COMPONENT_DEFINITION_OP, (vm, { op1: handle }) => { let definition = vm.constants.getValue(handle); assert(!!definition, `Missing component for ${handle}`); @@ -120,7 +150,7 @@ APPEND_OPCODES.add(Op.PushComponentDefinition, (vm, { op1: handle }) => { vm.stack.push(instance); }); -APPEND_OPCODES.add(Op.ResolveDynamicComponent, (vm, { op1: _isStrict }) => { +APPEND_OPCODES.add(VM_RESOLVE_DYNAMIC_COMPONENT_OP, (vm, { op1: _isStrict }) => { let stack = vm.stack; let component = check( valueForRef(check(stack.pop(), CheckReference)), @@ -153,7 +183,7 @@ APPEND_OPCODES.add(Op.ResolveDynamicComponent, (vm, { op1: _isStrict }) => { stack.push(definition); }); -APPEND_OPCODES.add(Op.ResolveCurriedComponent, (vm) => { +APPEND_OPCODES.add(VM_RESOLVE_CURRIED_COMPONENT_OP, (vm) => { let stack = vm.stack; let ref = check(stack.pop(), CheckReference); let value = valueForRef(ref); @@ -191,7 +221,7 @@ APPEND_OPCODES.add(Op.ResolveCurriedComponent, (vm) => { stack.push(definition); }); -APPEND_OPCODES.add(Op.PushDynamicComponentInstance, (vm) => { +APPEND_OPCODES.add(VM_PUSH_DYNAMIC_COMPONENT_INSTANCE_OP, (vm) => { let { stack } = vm; let definition = stack.pop(); @@ -207,7 +237,7 @@ APPEND_OPCODES.add(Op.PushDynamicComponentInstance, (vm) => { stack.push({ definition, capabilities, manager, state: null, handle: null, table: null }); }); -APPEND_OPCODES.add(Op.PushArgs, (vm, { op1: _names, op2: _blockNames, op3: flags }) => { +APPEND_OPCODES.add(VM_PUSH_ARGS_OP, (vm, { op1: _names, op2: _blockNames, op3: flags }) => { let stack = vm.stack; let names = vm.constants.getArray(_names); @@ -219,13 +249,13 @@ APPEND_OPCODES.add(Op.PushArgs, (vm, { op1: _names, op2: _blockNames, op3: flags stack.push(vm.args); }); -APPEND_OPCODES.add(Op.PushEmptyArgs, (vm) => { +APPEND_OPCODES.add(VM_PUSH_EMPTY_ARGS_OP, (vm) => { let { stack } = vm; stack.push(vm.args.empty(stack)); }); -APPEND_OPCODES.add(Op.CaptureArgs, (vm) => { +APPEND_OPCODES.add(VM_CAPTURE_ARGS_OP, (vm) => { let stack = vm.stack; let args = check(stack.pop(), CheckInstanceof(VMArgumentsImpl)); @@ -233,9 +263,9 @@ APPEND_OPCODES.add(Op.CaptureArgs, (vm) => { stack.push(capturedArgs); }); -APPEND_OPCODES.add(Op.PrepareArgs, (vm, { op1: _state }) => { +APPEND_OPCODES.add(VM_PREPARE_ARGS_OP, (vm, { op1: register }) => { let stack = vm.stack; - let instance = vm.fetchValue(_state); + let instance = vm.fetchValue(check(register, CheckRegister)); let args = check(stack.pop(), CheckInstanceof(VMArgumentsImpl)); let { definition } = instance; @@ -335,8 +365,8 @@ APPEND_OPCODES.add(Op.PrepareArgs, (vm, { op1: _state }) => { stack.push(args); }); -APPEND_OPCODES.add(Op.CreateComponent, (vm, { op1: flags, op2: _state }) => { - let instance = check(vm.fetchValue(_state), CheckComponentInstance); +APPEND_OPCODES.add(VM_CREATE_COMPONENT_OP, (vm, { op1: flags, op2: register }) => { + let instance = check(vm.fetchValue(check(register, CheckRegister)), CheckComponentInstance); let { definition, manager, capabilities } = instance; if (!managerHasCapability(manager, capabilities, InternalComponentCapabilities.createInstance)) { @@ -382,8 +412,11 @@ APPEND_OPCODES.add(Op.CreateComponent, (vm, { op1: flags, op2: _state }) => { } }); -APPEND_OPCODES.add(Op.RegisterComponentDestructor, (vm, { op1: _state }) => { - let { manager, state, capabilities } = check(vm.fetchValue(_state), CheckComponentInstance); +APPEND_OPCODES.add(VM_REGISTER_COMPONENT_DESTRUCTOR_OP, (vm, { op1: register }) => { + let { manager, state, capabilities } = check( + vm.fetchValue(check(register, CheckRegister)), + CheckComponentInstance + ); let d = manager.getDestroyable(state); @@ -401,11 +434,14 @@ APPEND_OPCODES.add(Op.RegisterComponentDestructor, (vm, { op1: _state }) => { if (d) vm.associateDestroyable(d); }); -APPEND_OPCODES.add(Op.BeginComponentTransaction, (vm, { op1: _state }) => { +APPEND_OPCODES.add(VM_BEGIN_COMPONENT_TRANSACTION_OP, (vm, { op1: register }) => { let name; if (import.meta.env.DEV) { - let { definition, manager } = check(vm.fetchValue(_state), CheckComponentInstance); + let { definition, manager } = check( + vm.fetchValue(check(register, CheckRegister)), + CheckComponentInstance + ); name = getDebugName(definition, manager); } @@ -414,11 +450,11 @@ APPEND_OPCODES.add(Op.BeginComponentTransaction, (vm, { op1: _state }) => { vm.elements().pushSimpleBlock(); }); -APPEND_OPCODES.add(Op.PutComponentOperations, (vm) => { +APPEND_OPCODES.add(VM_PUT_COMPONENT_OPERATIONS_OP, (vm) => { vm.loadValue($t0, new ComponentElementOperations()); }); -APPEND_OPCODES.add(Op.ComponentAttr, (vm, { op1: _name, op2: _trusting, op3: _namespace }) => { +APPEND_OPCODES.add(VM_COMPONENT_ATTR_OP, (vm, { op1: _name, op2: _trusting, op3: _namespace }) => { let name = vm.constants.getValue(_name); let trusting = vm.constants.getValue(_trusting); let reference = check(vm.stack.pop(), CheckReference); @@ -432,17 +468,20 @@ APPEND_OPCODES.add(Op.ComponentAttr, (vm, { op1: _name, op2: _trusting, op3: _na ); }); -APPEND_OPCODES.add(Op.StaticComponentAttr, (vm, { op1: _name, op2: _value, op3: _namespace }) => { - let name = vm.constants.getValue(_name); - let value = vm.constants.getValue(_value); - let namespace = _namespace ? vm.constants.getValue(_namespace) : null; - - check(vm.fetchValue($t0), CheckInstanceof(ComponentElementOperations)).setStaticAttribute( - name, - value, - namespace - ); -}); +APPEND_OPCODES.add( + VM_STATIC_COMPONENT_ATTR_OP, + (vm, { op1: _name, op2: _value, op3: _namespace }) => { + let name = vm.constants.getValue(_name); + let value = vm.constants.getValue(_value); + let namespace = _namespace ? vm.constants.getValue(_namespace) : null; + + check(vm.fetchValue($t0), CheckInstanceof(ComponentElementOperations)).setStaticAttribute( + name, + value, + namespace + ); + } +); type DeferredAttribute = { value: string | Reference; @@ -585,8 +624,11 @@ function setDeferredAttr( } } -APPEND_OPCODES.add(Op.DidCreateElement, (vm, { op1: _state }) => { - let { definition, state } = check(vm.fetchValue(_state), CheckComponentInstance); +APPEND_OPCODES.add(VM_DID_CREATE_ELEMENT_OP, (vm, { op1: register }) => { + let { definition, state } = check( + vm.fetchValue(check(register, CheckRegister)), + CheckComponentInstance + ); let { manager } = definition; let operations = check(vm.fetchValue($t0), CheckInstanceof(ComponentElementOperations)); @@ -598,14 +640,14 @@ APPEND_OPCODES.add(Op.DidCreateElement, (vm, { op1: _state }) => { ); }); -APPEND_OPCODES.add(Op.GetComponentSelf, (vm, { op1: _state, op2: _names }) => { - let instance = check(vm.fetchValue(_state), CheckComponentInstance); +APPEND_OPCODES.add(VM_GET_COMPONENT_SELF_OP, (vm, { op1: register, op2: _names }) => { + let instance = check(vm.fetchValue(check(register, CheckRegister)), CheckComponentInstance); let { definition, state } = instance; let { manager } = definition; let selfRef = manager.getSelf(state); if (vm.env.debugRenderTree !== undefined) { - let instance = check(vm.fetchValue(_state), CheckComponentInstance); + let instance = check(vm.fetchValue(check(register, CheckRegister)), CheckComponentInstance); let { definition, manager } = instance; let args: CapturedArguments; @@ -685,8 +727,11 @@ APPEND_OPCODES.add(Op.GetComponentSelf, (vm, { op1: _state, op2: _names }) => { vm.stack.push(selfRef); }); -APPEND_OPCODES.add(Op.GetComponentTagName, (vm, { op1: _state }) => { - let { definition, state } = check(vm.fetchValue(_state), CheckComponentInstance); +APPEND_OPCODES.add(VM_GET_COMPONENT_TAG_NAME_OP, (vm, { op1: register }) => { + let { definition, state } = check( + vm.fetchValue(check(register, CheckRegister)), + CheckComponentInstance + ); let { manager } = definition; let tagName = ( @@ -698,8 +743,8 @@ APPEND_OPCODES.add(Op.GetComponentTagName, (vm, { op1: _state }) => { }); // Dynamic Invocation Only -APPEND_OPCODES.add(Op.GetComponentLayout, (vm, { op1: _state }) => { - let instance = check(vm.fetchValue(_state), CheckComponentInstance); +APPEND_OPCODES.add(VM_GET_COMPONENT_LAYOUT_OP, (vm, { op1: register }) => { + let instance = check(vm.fetchValue(check(register, CheckRegister)), CheckComponentInstance); let { manager, definition } = instance; let { stack } = vm; @@ -731,7 +776,7 @@ APPEND_OPCODES.add(Op.GetComponentLayout, (vm, { op1: _state }) => { stack.push(handle); }); -APPEND_OPCODES.add(Op.Main, (vm, { op1: register }) => { +APPEND_OPCODES.add(VM_MAIN_OP, (vm, { op1: register }) => { let definition = check(vm.stack.pop(), CheckComponentDefinition); let invocation = check(vm.stack.pop(), CheckInvocation); @@ -747,25 +792,25 @@ APPEND_OPCODES.add(Op.Main, (vm, { op1: register }) => { lookup: null, }; - vm.loadValue(register, state); + vm.loadValue(check(register, CheckRegister), state); }); -APPEND_OPCODES.add(Op.PopulateLayout, (vm, { op1: _state }) => { +APPEND_OPCODES.add(VM_POPULATE_LAYOUT_OP, (vm, { op1: register }) => { let { stack } = vm; // In import.meta.env.DEV handles could be ErrHandle objects let handle = check(stack.pop(), CheckHandle); let table = check(stack.pop(), CheckProgramSymbolTable); - let state = check(vm.fetchValue(_state), CheckComponentInstance); + let state = check(vm.fetchValue(check(register, CheckRegister)), CheckComponentInstance); state.handle = handle; state.table = table; }); -APPEND_OPCODES.add(Op.VirtualRootScope, (vm, { op1: _state }) => { +APPEND_OPCODES.add(VM_VIRTUAL_ROOT_SCOPE_OP, (vm, { op1: register }) => { let { table, manager, capabilities, state } = check( - vm.fetchValue(_state), + vm.fetchValue(check(register, CheckRegister)), CheckFinishedComponentInstance ); @@ -793,8 +838,8 @@ APPEND_OPCODES.add(Op.VirtualRootScope, (vm, { op1: _state }) => { vm.pushRootScope(table.symbols.length + 1, owner); }); -APPEND_OPCODES.add(Op.SetupForEval, (vm, { op1: _state }) => { - let state = check(vm.fetchValue(_state), CheckFinishedComponentInstance); +APPEND_OPCODES.add(VM_SETUP_FOR_EVAL_OP, (vm, { op1: register }) => { + let state = check(vm.fetchValue(check(register, CheckRegister)), CheckFinishedComponentInstance); if (state.table.hasEval) { let lookup = (state.lookup = dict()); @@ -802,8 +847,8 @@ APPEND_OPCODES.add(Op.SetupForEval, (vm, { op1: _state }) => { } }); -APPEND_OPCODES.add(Op.SetNamedVariables, (vm, { op1: _state }) => { - let state = check(vm.fetchValue(_state), CheckFinishedComponentInstance); +APPEND_OPCODES.add(VM_SET_NAMED_VARIABLES_OP, (vm, { op1: register }) => { + let state = check(vm.fetchValue(check(register, CheckRegister)), CheckFinishedComponentInstance); let scope = vm.scope(); let args = check(vm.stack.peek(), CheckArguments); @@ -833,8 +878,8 @@ function bindBlock( if (state.lookup) state.lookup[symbolName] = block; } -APPEND_OPCODES.add(Op.SetBlocks, (vm, { op1: _state }) => { - let state = check(vm.fetchValue(_state), CheckFinishedComponentInstance); +APPEND_OPCODES.add(VM_SET_BLOCKS_OP, (vm, { op1: register }) => { + let state = check(vm.fetchValue(check(register, CheckRegister)), CheckFinishedComponentInstance); let { blocks } = check(vm.stack.peek(), CheckArguments); for (const [i] of enumerate(blocks.names)) { @@ -843,14 +888,14 @@ APPEND_OPCODES.add(Op.SetBlocks, (vm, { op1: _state }) => { }); // Dynamic Invocation Only -APPEND_OPCODES.add(Op.InvokeComponentLayout, (vm, { op1: _state }) => { - let state = check(vm.fetchValue(_state), CheckFinishedComponentInstance); +APPEND_OPCODES.add(VM_INVOKE_COMPONENT_LAYOUT_OP, (vm, { op1: register }) => { + let state = check(vm.fetchValue(check(register, CheckRegister)), CheckFinishedComponentInstance); vm.call(state.handle); }); -APPEND_OPCODES.add(Op.DidRenderLayout, (vm, { op1: _state }) => { - let instance = check(vm.fetchValue(_state), CheckComponentInstance); +APPEND_OPCODES.add(VM_DID_RENDER_LAYOUT_OP, (vm, { op1: register }) => { + let instance = check(vm.fetchValue(check(register, CheckRegister)), CheckComponentInstance); let { manager, state, capabilities } = instance; let bounds = vm.elements().popBlock(); @@ -881,7 +926,7 @@ APPEND_OPCODES.add(Op.DidRenderLayout, (vm, { op1: _state }) => { } }); -APPEND_OPCODES.add(Op.CommitComponentTransaction, (vm) => { +APPEND_OPCODES.add(VM_COMMIT_COMPONENT_TRANSACTION_OP, (vm) => { vm.commitCacheGroup(); }); diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/content.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/content.ts index bc54a0a552..c15e76f162 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/content.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/content.ts @@ -1,3 +1,12 @@ +import { + VM_APPEND_DOCUMENT_FRAGMENT_OP, + VM_APPEND_HTML_OP, + VM_APPEND_NODE_OP, + VM_APPEND_SAFE_HTML_OP, + VM_APPEND_TEXT_OP, + VM_CONTENT_TYPE_OP, + VM_DYNAMIC_CONTENT_TYPE_OP, +} from '@glimmer/constants'; import { check, CheckDocumentFragment, @@ -8,7 +17,7 @@ import { import { hasInternalComponentManager, hasInternalHelperManager } from '@glimmer/manager'; import { isConstRef, valueForRef } from '@glimmer/reference'; import { isObject } from '@glimmer/util'; -import { ContentType, CurriedType, Op } from '@glimmer/vm'; +import { ContentType, CurriedType } from '@glimmer/vm'; import { isCurriedType } from '../../curried-value'; import { isEmpty, isFragment, isNode, isSafeString, shouldCoerce } from '../../dom/normalize'; @@ -64,7 +73,7 @@ function toDynamicContentType(value: unknown) { } } -APPEND_OPCODES.add(Op.ContentType, (vm) => { +APPEND_OPCODES.add(VM_CONTENT_TYPE_OP, (vm) => { let reference = check(vm.stack.peek(), CheckReference); vm.stack.push(toContentType(valueForRef(reference))); @@ -74,7 +83,7 @@ APPEND_OPCODES.add(Op.ContentType, (vm) => { } }); -APPEND_OPCODES.add(Op.DynamicContentType, (vm) => { +APPEND_OPCODES.add(VM_DYNAMIC_CONTENT_TYPE_OP, (vm) => { let reference = check(vm.stack.peek(), CheckReference); vm.stack.push(toDynamicContentType(valueForRef(reference))); @@ -84,7 +93,7 @@ APPEND_OPCODES.add(Op.DynamicContentType, (vm) => { } }); -APPEND_OPCODES.add(Op.AppendHTML, (vm) => { +APPEND_OPCODES.add(VM_APPEND_HTML_OP, (vm) => { let reference = check(vm.stack.pop(), CheckReference); let rawValue = valueForRef(reference); @@ -93,7 +102,7 @@ APPEND_OPCODES.add(Op.AppendHTML, (vm) => { vm.elements().appendDynamicHTML(value); }); -APPEND_OPCODES.add(Op.AppendSafeHTML, (vm) => { +APPEND_OPCODES.add(VM_APPEND_SAFE_HTML_OP, (vm) => { let reference = check(vm.stack.pop(), CheckReference); let rawValue = check(valueForRef(reference), CheckSafeString).toHTML(); @@ -102,7 +111,7 @@ APPEND_OPCODES.add(Op.AppendSafeHTML, (vm) => { vm.elements().appendDynamicHTML(value); }); -APPEND_OPCODES.add(Op.AppendText, (vm) => { +APPEND_OPCODES.add(VM_APPEND_TEXT_OP, (vm) => { let reference = check(vm.stack.pop(), CheckReference); let rawValue = valueForRef(reference); @@ -115,7 +124,7 @@ APPEND_OPCODES.add(Op.AppendText, (vm) => { } }); -APPEND_OPCODES.add(Op.AppendDocumentFragment, (vm) => { +APPEND_OPCODES.add(VM_APPEND_DOCUMENT_FRAGMENT_OP, (vm) => { let reference = check(vm.stack.pop(), CheckReference); let value = check(valueForRef(reference), CheckDocumentFragment); @@ -123,7 +132,7 @@ APPEND_OPCODES.add(Op.AppendDocumentFragment, (vm) => { vm.elements().appendDynamicFragment(value); }); -APPEND_OPCODES.add(Op.AppendNode, (vm) => { +APPEND_OPCODES.add(VM_APPEND_NODE_OP, (vm) => { let reference = check(vm.stack.pop(), CheckReference); let value = check(valueForRef(reference), CheckNode); diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/debugger.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/debugger.ts index ce742c6b14..1cbf36ffed 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/debugger.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/debugger.ts @@ -1,9 +1,9 @@ import type { Scope } from '@glimmer/interfaces'; import type { Reference } from '@glimmer/reference'; +import { decodeHandle, VM_DEBUGGER_OP } from '@glimmer/constants'; import { unwrap } from '@glimmer/debug-util'; import { childRefFor, valueForRef } from '@glimmer/reference'; -import { decodeHandle, dict } from '@glimmer/util'; -import { Op } from '@glimmer/vm'; +import { dict } from '@glimmer/util'; import { APPEND_OPCODES } from '../../opcodes'; @@ -71,7 +71,7 @@ class ScopeInspector { } } -APPEND_OPCODES.add(Op.Debugger, (vm, { op1: _symbols, op2: _debugInfo }) => { +APPEND_OPCODES.add(VM_DEBUGGER_OP, (vm, { op1: _symbols, op2: _debugInfo }) => { let symbols = vm.constants.getArray(_symbols); let debugInfo = vm.constants.getArray(decodeHandle(_debugInfo)); let inspector = new ScopeInspector(vm.scope(), symbols, debugInfo); diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/dom.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/dom.ts index cd2f5ad019..79965d7e65 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/dom.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/dom.ts @@ -11,12 +11,26 @@ import type { } from '@glimmer/interfaces'; import type { Reference } from '@glimmer/reference'; import type { Revision, Tag } from '@glimmer/validator'; +import { + VM_CLOSE_ELEMENT_OP, + VM_COMMENT_OP, + VM_DYNAMIC_ATTR_OP, + VM_DYNAMIC_MODIFIER_OP, + VM_FLUSH_ELEMENT_OP, + VM_MODIFIER_OP, + VM_OPEN_DYNAMIC_ELEMENT_OP, + VM_OPEN_ELEMENT_OP, + VM_POP_REMOTE_ELEMENT_OP, + VM_PUSH_REMOTE_ELEMENT_OP, + VM_STATIC_ATTR_OP, + VM_TEXT_OP, +} from '@glimmer/constants'; import { check, CheckElement, CheckMaybe, CheckNode, - CheckOption, + CheckNullable, CheckString, } from '@glimmer/debug'; import { debugToString, expect } from '@glimmer/debug-util'; @@ -25,7 +39,7 @@ import { getInternalModifierManager } from '@glimmer/manager'; import { createComputeRef, isConstRef, valueForRef } from '@glimmer/reference'; import { isObject } from '@glimmer/util'; import { consumeTag, CURRENT_TAG, validateTag, valueForTag } from '@glimmer/validator'; -import { $t0, CurriedTypes, Op } from '@glimmer/vm'; +import { $t0, CurriedTypes } from '@glimmer/vm'; import type { CurriedValue } from '../../curried-value'; import type { DynamicAttribute } from '../../vm/attributes/dynamic'; @@ -36,30 +50,30 @@ import { createCapturedArgs } from '../../vm/arguments'; import { CheckArguments, CheckOperations, CheckReference } from './-debug-strip'; import { Assert } from './vm'; -APPEND_OPCODES.add(Op.Text, (vm, { op1: text }) => { +APPEND_OPCODES.add(VM_TEXT_OP, (vm, { op1: text }) => { vm.elements().appendText(vm.constants.getValue(text)); }); -APPEND_OPCODES.add(Op.Comment, (vm, { op1: text }) => { +APPEND_OPCODES.add(VM_COMMENT_OP, (vm, { op1: text }) => { vm.elements().appendComment(vm.constants.getValue(text)); }); -APPEND_OPCODES.add(Op.OpenElement, (vm, { op1: tag }) => { +APPEND_OPCODES.add(VM_OPEN_ELEMENT_OP, (vm, { op1: tag }) => { vm.elements().openElement(vm.constants.getValue(tag)); }); -APPEND_OPCODES.add(Op.OpenDynamicElement, (vm) => { +APPEND_OPCODES.add(VM_OPEN_DYNAMIC_ELEMENT_OP, (vm) => { let tagName = check(valueForRef(check(vm.stack.pop(), CheckReference)), CheckString); vm.elements().openElement(tagName); }); -APPEND_OPCODES.add(Op.PushRemoteElement, (vm) => { +APPEND_OPCODES.add(VM_PUSH_REMOTE_ELEMENT_OP, (vm) => { let elementRef = check(vm.stack.pop(), CheckReference); let insertBeforeRef = check(vm.stack.pop(), CheckReference); let guidRef = check(vm.stack.pop(), CheckReference); let element = check(valueForRef(elementRef), CheckElement); - let insertBefore = check(valueForRef(insertBeforeRef), CheckMaybe(CheckOption(CheckNode))); + let insertBefore = check(valueForRef(insertBeforeRef), CheckMaybe(CheckNullable(CheckNode))); let guid = valueForRef(guidRef) as string; if (!isConstRef(elementRef)) { @@ -95,7 +109,7 @@ APPEND_OPCODES.add(Op.PushRemoteElement, (vm) => { } }); -APPEND_OPCODES.add(Op.PopRemoteElement, (vm) => { +APPEND_OPCODES.add(VM_POP_REMOTE_ELEMENT_OP, (vm) => { let bounds = vm.elements().popRemoteElement(); if (vm.env.debugRenderTree !== undefined) { @@ -104,7 +118,7 @@ APPEND_OPCODES.add(Op.PopRemoteElement, (vm) => { } }); -APPEND_OPCODES.add(Op.FlushElement, (vm) => { +APPEND_OPCODES.add(VM_FLUSH_ELEMENT_OP, (vm) => { let operations = check(vm.fetchValue($t0), CheckOperations); let modifiers: Nullable = null; @@ -116,7 +130,7 @@ APPEND_OPCODES.add(Op.FlushElement, (vm) => { vm.elements().flushElement(modifiers); }); -APPEND_OPCODES.add(Op.CloseElement, (vm) => { +APPEND_OPCODES.add(VM_CLOSE_ELEMENT_OP, (vm) => { let modifiers = vm.elements().closeElement(); if (modifiers !== null) { @@ -131,7 +145,7 @@ APPEND_OPCODES.add(Op.CloseElement, (vm) => { } }); -APPEND_OPCODES.add(Op.Modifier, (vm, { op1: handle }) => { +APPEND_OPCODES.add(VM_MODIFIER_OP, (vm, { op1: handle }) => { if (vm.env.isInteractive === false) { return; } @@ -173,7 +187,7 @@ APPEND_OPCODES.add(Op.Modifier, (vm, { op1: handle }) => { } }); -APPEND_OPCODES.add(Op.DynamicModifier, (vm) => { +APPEND_OPCODES.add(VM_DYNAMIC_MODIFIER_OP, (vm) => { if (vm.env.isInteractive === false) { return; } @@ -355,7 +369,7 @@ export class UpdateDynamicModifierOpcode implements UpdatingOpcode { } } -APPEND_OPCODES.add(Op.StaticAttr, (vm, { op1: _name, op2: _value, op3: _namespace }) => { +APPEND_OPCODES.add(VM_STATIC_ATTR_OP, (vm, { op1: _name, op2: _value, op3: _namespace }) => { let name = vm.constants.getValue(_name); let value = vm.constants.getValue(_value); let namespace = _namespace ? vm.constants.getValue(_namespace) : null; @@ -363,7 +377,7 @@ APPEND_OPCODES.add(Op.StaticAttr, (vm, { op1: _name, op2: _value, op3: _namespac vm.elements().setStaticAttribute(name, value, namespace); }); -APPEND_OPCODES.add(Op.DynamicAttr, (vm, { op1: _name, op2: _trusting, op3: _namespace }) => { +APPEND_OPCODES.add(VM_DYNAMIC_ATTR_OP, (vm, { op1: _name, op2: _trusting, op3: _namespace }) => { let name = vm.constants.getValue(_name); let trusting = vm.constants.getValue(_trusting); let reference = check(vm.stack.pop(), CheckReference); diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/expressions.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/expressions.ts index 67e8886927..9d6478357c 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/expressions.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/expressions.ts @@ -8,12 +8,32 @@ import type { VM as PublicVM, } from '@glimmer/interfaces'; import type { Reference } from '@glimmer/reference'; +import { + decodeHandle, + VM_CONCAT_OP, + VM_CURRY_OP, + VM_DYNAMIC_HELPER_OP, + VM_GET_BLOCK_OP, + VM_GET_DYNAMIC_VAR_OP, + VM_GET_PROPERTY_OP, + VM_GET_VARIABLE_OP, + VM_HAS_BLOCK_OP, + VM_HAS_BLOCK_PARAMS_OP, + VM_HELPER_OP, + VM_IF_INLINE_OP, + VM_LOG_OP, + VM_NOT_OP, + VM_ROOT_SCOPE_OP, + VM_SET_BLOCK_OP, + VM_SET_VARIABLE_OP, + VM_SPREAD_BLOCK_OP, +} from '@glimmer/constants'; import { check, CheckBlockSymbolTable, CheckHandle, CheckMaybe, - CheckOption, + CheckNullable, CheckOr, } from '@glimmer/debug'; import { assert, debugToString } from '@glimmer/debug-util'; @@ -28,8 +48,8 @@ import { UNDEFINED_REFERENCE, valueForRef, } from '@glimmer/reference'; -import { assign, decodeHandle, isObject } from '@glimmer/util'; -import { $v0, CurriedTypes, Op } from '@glimmer/vm'; +import { assign, isObject } from '@glimmer/util'; +import { $v0, CurriedTypes } from '@glimmer/vm'; import { isCurriedType, resolveCurriedValue } from '../../curried-value'; import { APPEND_OPCODES } from '../../opcodes'; @@ -49,7 +69,7 @@ import { export type FunctionExpression = (vm: PublicVM) => Reference; -APPEND_OPCODES.add(Op.Curry, (vm, { op1: type, op2: _isStrict }) => { +APPEND_OPCODES.add(VM_CURRY_OP, (vm, { op1: type, op2: _isStrict }) => { let stack = vm.stack; let definition = check(stack.pop(), CheckReference); @@ -71,7 +91,7 @@ APPEND_OPCODES.add(Op.Curry, (vm, { op1: type, op2: _isStrict }) => { ); }); -APPEND_OPCODES.add(Op.DynamicHelper, (vm) => { +APPEND_OPCODES.add(VM_DYNAMIC_HELPER_OP, (vm) => { let stack = vm.stack; let ref = check(stack.pop(), CheckReference); let args = check(stack.pop(), CheckArguments).capture(); @@ -149,7 +169,7 @@ function resolveHelper(definition: HelperDefinitionState, ref: Reference): Helpe return helper!; } -APPEND_OPCODES.add(Op.Helper, (vm, { op1: handle }) => { +APPEND_OPCODES.add(VM_HELPER_OP, (vm, { op1: handle }) => { let stack = vm.stack; let helper = check(vm.constants.getValue(handle), CheckHelper); let args = check(stack.pop(), CheckArguments); @@ -162,18 +182,18 @@ APPEND_OPCODES.add(Op.Helper, (vm, { op1: handle }) => { vm.loadValue($v0, value); }); -APPEND_OPCODES.add(Op.GetVariable, (vm, { op1: symbol }) => { +APPEND_OPCODES.add(VM_GET_VARIABLE_OP, (vm, { op1: symbol }) => { let expr = vm.referenceForSymbol(symbol); vm.stack.push(expr); }); -APPEND_OPCODES.add(Op.SetVariable, (vm, { op1: symbol }) => { +APPEND_OPCODES.add(VM_SET_VARIABLE_OP, (vm, { op1: symbol }) => { let expr = check(vm.stack.pop(), CheckReference); vm.scope().bindSymbol(symbol, expr); }); -APPEND_OPCODES.add(Op.SetBlock, (vm, { op1: symbol }) => { +APPEND_OPCODES.add(VM_SET_BLOCK_OP, (vm, { op1: symbol }) => { let handle = check(vm.stack.pop(), CheckCompilableBlock); let scope = check(vm.stack.pop(), CheckScope); let table = check(vm.stack.pop(), CheckBlockSymbolTable); @@ -181,38 +201,26 @@ APPEND_OPCODES.add(Op.SetBlock, (vm, { op1: symbol }) => { vm.scope().bindBlock(symbol, [handle, scope, table]); }); -APPEND_OPCODES.add(Op.ResolveMaybeLocal, (vm, { op1: _name }) => { - let name = vm.constants.getValue(_name); - let locals = vm.scope().getPartialMap()!; - - let ref = locals[name]; - if (ref === undefined) { - ref = childRefFor(vm.getSelf(), name); - } - - vm.stack.push(ref); -}); - -APPEND_OPCODES.add(Op.RootScope, (vm, { op1: symbols }) => { +APPEND_OPCODES.add(VM_ROOT_SCOPE_OP, (vm, { op1: symbols }) => { vm.pushRootScope(symbols, vm.getOwner()); }); -APPEND_OPCODES.add(Op.GetProperty, (vm, { op1: _key }) => { +APPEND_OPCODES.add(VM_GET_PROPERTY_OP, (vm, { op1: _key }) => { let key = vm.constants.getValue(_key); let expr = check(vm.stack.pop(), CheckReference); vm.stack.push(childRefFor(expr, key)); }); -APPEND_OPCODES.add(Op.GetBlock, (vm, { op1: _block }) => { +APPEND_OPCODES.add(VM_GET_BLOCK_OP, (vm, { op1: _block }) => { let { stack } = vm; let block = vm.scope().getBlock(_block); stack.push(block); }); -APPEND_OPCODES.add(Op.SpreadBlock, (vm) => { +APPEND_OPCODES.add(VM_SPREAD_BLOCK_OP, (vm) => { let { stack } = vm; - let block = check(stack.pop(), CheckOption(CheckOr(CheckScopeBlock, CheckUndefinedReference))); + let block = check(stack.pop(), CheckNullable(CheckOr(CheckScopeBlock, CheckUndefinedReference))); if (block && !isUndefinedReference(block)) { let [handleOrCompilable, scope, table] = block; @@ -235,9 +243,9 @@ function isUndefinedReference(input: ScopeBlock | Reference): input is Reference return input === UNDEFINED_REFERENCE; } -APPEND_OPCODES.add(Op.HasBlock, (vm) => { +APPEND_OPCODES.add(VM_HAS_BLOCK_OP, (vm) => { let { stack } = vm; - let block = check(stack.pop(), CheckOption(CheckOr(CheckScopeBlock, CheckUndefinedReference))); + let block = check(stack.pop(), CheckNullable(CheckOr(CheckScopeBlock, CheckUndefinedReference))); if (block && !isUndefinedReference(block)) { stack.push(TRUE_REFERENCE); @@ -246,7 +254,7 @@ APPEND_OPCODES.add(Op.HasBlock, (vm) => { } }); -APPEND_OPCODES.add(Op.HasBlockParams, (vm) => { +APPEND_OPCODES.add(VM_HAS_BLOCK_PARAMS_OP, (vm) => { // FIXME(mmun): should only need to push the symbol table let block = vm.stack.pop(); let scope = vm.stack.pop(); @@ -259,7 +267,7 @@ APPEND_OPCODES.add(Op.HasBlockParams, (vm) => { vm.stack.push(hasBlockParams ? TRUE_REFERENCE : FALSE_REFERENCE); }); -APPEND_OPCODES.add(Op.Concat, (vm, { op1: count }) => { +APPEND_OPCODES.add(VM_CONCAT_OP, (vm, { op1: count }) => { let out: Array> = new Array(count); for (let i = count; i > 0; i--) { @@ -270,7 +278,7 @@ APPEND_OPCODES.add(Op.Concat, (vm, { op1: count }) => { vm.stack.push(createConcatRef(out)); }); -APPEND_OPCODES.add(Op.IfInline, (vm) => { +APPEND_OPCODES.add(VM_IF_INLINE_OP, (vm) => { let condition = check(vm.stack.pop(), CheckReference); let truthy = check(vm.stack.pop(), CheckReference); let falsy = check(vm.stack.pop(), CheckReference); @@ -286,7 +294,7 @@ APPEND_OPCODES.add(Op.IfInline, (vm) => { ); }); -APPEND_OPCODES.add(Op.Not, (vm) => { +APPEND_OPCODES.add(VM_NOT_OP, (vm) => { let ref = check(vm.stack.pop(), CheckReference); vm.stack.push( @@ -296,7 +304,7 @@ APPEND_OPCODES.add(Op.Not, (vm) => { ); }); -APPEND_OPCODES.add(Op.GetDynamicVar, (vm) => { +APPEND_OPCODES.add(VM_GET_DYNAMIC_VAR_OP, (vm) => { let scope = vm.dynamicScope(); let stack = vm.stack; let nameRef = check(stack.pop(), CheckReference); @@ -309,7 +317,7 @@ APPEND_OPCODES.add(Op.GetDynamicVar, (vm) => { ); }); -APPEND_OPCODES.add(Op.Log, (vm) => { +APPEND_OPCODES.add(VM_LOG_OP, (vm) => { let { positional } = check(vm.stack.pop(), CheckArguments).capture(); vm.loadValue( diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/lists.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/lists.ts index b9318d57a3..44af2c478b 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/lists.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/lists.ts @@ -1,12 +1,12 @@ +import { VM_ENTER_LIST_OP, VM_EXIT_LIST_OP, VM_ITERATE_OP } from '@glimmer/constants'; import { check } from '@glimmer/debug'; import { createIteratorRef, valueForRef } from '@glimmer/reference'; -import { Op } from '@glimmer/vm'; import { APPEND_OPCODES } from '../../opcodes'; import { CheckIterator, CheckReference } from './-debug-strip'; import { AssertFilter } from './vm'; -APPEND_OPCODES.add(Op.EnterList, (vm, { op1: relativeStart, op2: elseTarget }) => { +APPEND_OPCODES.add(VM_ENTER_LIST_OP, (vm, { op1: relativeStart, op2: elseTarget }) => { let stack = vm.stack; let listRef = check(stack.pop(), CheckReference); let keyRef = check(stack.pop(), CheckReference); @@ -28,11 +28,11 @@ APPEND_OPCODES.add(Op.EnterList, (vm, { op1: relativeStart, op2: elseTarget }) = } }); -APPEND_OPCODES.add(Op.ExitList, (vm) => { +APPEND_OPCODES.add(VM_EXIT_LIST_OP, (vm) => { vm.exitList(); }); -APPEND_OPCODES.add(Op.Iterate, (vm, { op1: breaks }) => { +APPEND_OPCODES.add(VM_ITERATE_OP, (vm, { op1: breaks }) => { let stack = vm.stack; let iterator = check(stack.peek(), CheckIterator); let item = iterator.next(); diff --git a/packages/@glimmer/runtime/lib/compiled/opcodes/vm.ts b/packages/@glimmer/runtime/lib/compiled/opcodes/vm.ts index dfce41f256..ae7e236b75 100644 --- a/packages/@glimmer/runtime/lib/compiled/opcodes/vm.ts +++ b/packages/@glimmer/runtime/lib/compiled/opcodes/vm.ts @@ -1,14 +1,45 @@ import type { CompilableTemplate, Nullable, UpdatingOpcode } from '@glimmer/interfaces'; import type { Reference } from '@glimmer/reference'; import type { Revision, Tag } from '@glimmer/validator'; +import { + decodeHandle, + decodeImmediate, + isHandle, + VM_ASSERT_SAME_OP, + VM_BIND_DYNAMIC_SCOPE_OP, + VM_CHILD_SCOPE_OP, + VM_COMPILE_BLOCK_OP, + VM_CONSTANT_OP, + VM_CONSTANT_REFERENCE_OP, + VM_DUP_OP, + VM_ENTER_OP, + VM_EXIT_OP, + VM_FETCH_OP, + VM_INVOKE_YIELD_OP, + VM_JUMP_EQ_OP, + VM_JUMP_IF_OP, + VM_JUMP_UNLESS_OP, + VM_LOAD_OP, + VM_POP_DYNAMIC_SCOPE_OP, + VM_POP_OP, + VM_POP_SCOPE_OP, + VM_PRIMITIVE_OP, + VM_PRIMITIVE_REFERENCE_OP, + VM_PUSH_BLOCK_SCOPE_OP, + VM_PUSH_DYNAMIC_SCOPE_OP, + VM_PUSH_SYMBOL_TABLE_OP, + VM_TO_BOOLEAN_OP, +} from '@glimmer/constants'; import { check, CheckBlockSymbolTable, CheckHandle, CheckInstanceof, + CheckNullable, CheckNumber, - CheckOption, CheckPrimitive, + CheckRegister, + CheckSyscallRegister, } from '@glimmer/debug'; import { assert, expect, unwrap } from '@glimmer/debug-util'; import { toBool } from '@glimmer/global-context'; @@ -23,7 +54,6 @@ import { UNDEFINED_REFERENCE, valueForRef, } from '@glimmer/reference'; -import { decodeHandle, decodeImmediate, isHandle } from '@glimmer/util'; import { beginTrackFrame, CONSTANT_TAG, @@ -33,7 +63,6 @@ import { validateTag, valueForTag, } from '@glimmer/validator'; -import { Op } from '@glimmer/vm'; import type { UpdatingVM } from '../../vm'; import type { VM } from '../../vm/append'; @@ -43,23 +72,23 @@ import { VMArgumentsImpl } from '../../vm/arguments'; import { CheckReference, CheckScope } from './-debug-strip'; import { stackAssert } from './assert'; -APPEND_OPCODES.add(Op.ChildScope, (vm) => vm.pushChildScope()); +APPEND_OPCODES.add(VM_CHILD_SCOPE_OP, (vm) => vm.pushChildScope()); -APPEND_OPCODES.add(Op.PopScope, (vm) => vm.popScope()); +APPEND_OPCODES.add(VM_POP_SCOPE_OP, (vm) => vm.popScope()); -APPEND_OPCODES.add(Op.PushDynamicScope, (vm) => vm.pushDynamicScope()); +APPEND_OPCODES.add(VM_PUSH_DYNAMIC_SCOPE_OP, (vm) => vm.pushDynamicScope()); -APPEND_OPCODES.add(Op.PopDynamicScope, (vm) => vm.popDynamicScope()); +APPEND_OPCODES.add(VM_POP_DYNAMIC_SCOPE_OP, (vm) => vm.popDynamicScope()); -APPEND_OPCODES.add(Op.Constant, (vm, { op1: other }) => { +APPEND_OPCODES.add(VM_CONSTANT_OP, (vm, { op1: other }) => { vm.stack.push(vm.constants.getValue(decodeHandle(other))); }); -APPEND_OPCODES.add(Op.ConstantReference, (vm, { op1: other }) => { +APPEND_OPCODES.add(VM_CONSTANT_REFERENCE_OP, (vm, { op1: other }) => { vm.stack.push(createConstRef(vm.constants.getValue(decodeHandle(other)), false)); }); -APPEND_OPCODES.add(Op.Primitive, (vm, { op1: primitive }) => { +APPEND_OPCODES.add(VM_PRIMITIVE_OP, (vm, { op1: primitive }) => { let stack = vm.stack; if (isHandle(primitive)) { @@ -72,7 +101,7 @@ APPEND_OPCODES.add(Op.Primitive, (vm, { op1: primitive }) => { } }); -APPEND_OPCODES.add(Op.PrimitiveReference, (vm) => { +APPEND_OPCODES.add(VM_PRIMITIVE_REFERENCE_OP, (vm) => { let stack = vm.stack; let value = check(stack.pop(), CheckPrimitive); let ref; @@ -92,47 +121,47 @@ APPEND_OPCODES.add(Op.PrimitiveReference, (vm) => { stack.push(ref); }); -APPEND_OPCODES.add(Op.Dup, (vm, { op1: register, op2: offset }) => { - let position = check(vm.fetchValue(register), CheckNumber) - offset; +APPEND_OPCODES.add(VM_DUP_OP, (vm, { op1: register, op2: offset }) => { + let position = check(vm.fetchValue(check(register, CheckRegister)), CheckNumber) - offset; vm.stack.dup(position); }); -APPEND_OPCODES.add(Op.Pop, (vm, { op1: count }) => { +APPEND_OPCODES.add(VM_POP_OP, (vm, { op1: count }) => { vm.stack.pop(count); }); -APPEND_OPCODES.add(Op.Load, (vm, { op1: register }) => { - vm.load(register); +APPEND_OPCODES.add(VM_LOAD_OP, (vm, { op1: register }) => { + vm.load(check(register, CheckSyscallRegister)); }); -APPEND_OPCODES.add(Op.Fetch, (vm, { op1: register }) => { - vm.fetch(register); +APPEND_OPCODES.add(VM_FETCH_OP, (vm, { op1: register }) => { + vm.fetch(check(register, CheckSyscallRegister)); }); -APPEND_OPCODES.add(Op.BindDynamicScope, (vm, { op1: _names }) => { +APPEND_OPCODES.add(VM_BIND_DYNAMIC_SCOPE_OP, (vm, { op1: _names }) => { let names = vm.constants.getArray(_names); vm.bindDynamicScope(names); }); -APPEND_OPCODES.add(Op.Enter, (vm, { op1: args }) => { +APPEND_OPCODES.add(VM_ENTER_OP, (vm, { op1: args }) => { vm.enter(args); }); -APPEND_OPCODES.add(Op.Exit, (vm) => { +APPEND_OPCODES.add(VM_EXIT_OP, (vm) => { vm.exit(); }); -APPEND_OPCODES.add(Op.PushSymbolTable, (vm, { op1: _table }) => { +APPEND_OPCODES.add(VM_PUSH_SYMBOL_TABLE_OP, (vm, { op1: _table }) => { let stack = vm.stack; stack.push(vm.constants.getValue(_table)); }); -APPEND_OPCODES.add(Op.PushBlockScope, (vm) => { +APPEND_OPCODES.add(VM_PUSH_BLOCK_SCOPE_OP, (vm) => { let stack = vm.stack; stack.push(vm.scope()); }); -APPEND_OPCODES.add(Op.CompileBlock, (vm: VM) => { +APPEND_OPCODES.add(VM_COMPILE_BLOCK_OP, (vm: VM) => { let stack = vm.stack; let block = stack.pop | 0>(); @@ -143,21 +172,25 @@ APPEND_OPCODES.add(Op.CompileBlock, (vm: VM) => { } }); -APPEND_OPCODES.add(Op.InvokeYield, (vm) => { +APPEND_OPCODES.add(VM_INVOKE_YIELD_OP, (vm) => { let { stack } = vm; - let handle = check(stack.pop(), CheckOption(CheckHandle)); - let scope = check(stack.pop(), CheckOption(CheckScope)); - let table = check(stack.pop(), CheckOption(CheckBlockSymbolTable)); + let handle = check(stack.pop(), CheckNullable(CheckHandle)); + let scope = check(stack.pop(), CheckNullable(CheckScope)); + let table = check(stack.pop(), CheckNullable(CheckBlockSymbolTable)); assert( table === null || (table && typeof table === 'object' && Array.isArray(table.parameters)), - stackAssert('Option', table) + stackAssert('Nullable', table) ); let args = check(stack.pop(), CheckInstanceof(VMArgumentsImpl)); - if (table === null) { + if (table === null || handle === null) { + assert( + handle === null && table === null, + `Expected both handle and table to be null if either is null` + ); // To balance the pop{Frame,Scope} vm.pushFrame(); vm.pushScope(scope ?? vm.scope()); @@ -183,10 +216,11 @@ APPEND_OPCODES.add(Op.InvokeYield, (vm) => { vm.pushFrame(); vm.pushScope(invokingScope); - vm.call(handle!); + + vm.call(handle); }); -APPEND_OPCODES.add(Op.JumpIf, (vm, { op1: target }) => { +APPEND_OPCODES.add(VM_JUMP_IF_OP, (vm, { op1: target }) => { let reference = check(vm.stack.pop(), CheckReference); let value = Boolean(valueForRef(reference)); @@ -203,7 +237,7 @@ APPEND_OPCODES.add(Op.JumpIf, (vm, { op1: target }) => { } }); -APPEND_OPCODES.add(Op.JumpUnless, (vm, { op1: target }) => { +APPEND_OPCODES.add(VM_JUMP_UNLESS_OP, (vm, { op1: target }) => { let reference = check(vm.stack.pop(), CheckReference); let value = Boolean(valueForRef(reference)); @@ -220,7 +254,7 @@ APPEND_OPCODES.add(Op.JumpUnless, (vm, { op1: target }) => { } }); -APPEND_OPCODES.add(Op.JumpEq, (vm, { op1: target, op2: comparison }) => { +APPEND_OPCODES.add(VM_JUMP_EQ_OP, (vm, { op1: target, op2: comparison }) => { let other = check(vm.stack.peek(), CheckNumber); if (other === comparison) { @@ -228,7 +262,7 @@ APPEND_OPCODES.add(Op.JumpEq, (vm, { op1: target, op2: comparison }) => { } }); -APPEND_OPCODES.add(Op.AssertSame, (vm) => { +APPEND_OPCODES.add(VM_ASSERT_SAME_OP, (vm) => { let reference = check(vm.stack.peek(), CheckReference); if (isConstRef(reference) === false) { @@ -236,7 +270,7 @@ APPEND_OPCODES.add(Op.AssertSame, (vm) => { } }); -APPEND_OPCODES.add(Op.ToBoolean, (vm) => { +APPEND_OPCODES.add(VM_TO_BOOLEAN_OP, (vm) => { let { stack } = vm; let valueRef = check(stack.pop(), CheckReference); diff --git a/packages/@glimmer/runtime/lib/dom/api.ts b/packages/@glimmer/runtime/lib/dom/api.ts index e81a9cc5ee..90339aac1c 100644 --- a/packages/@glimmer/runtime/lib/dom/api.ts +++ b/packages/@glimmer/runtime/lib/dom/api.ts @@ -6,8 +6,8 @@ import type { SimpleDocument, SimpleElement, } from '@glimmer/interfaces'; +import { NS_SVG } from '@glimmer/constants'; import { castToSimple } from '@glimmer/debug-util'; -import { NS_SVG } from '@glimmer/util'; import { applySVGInnerHTMLFix } from '../compat/svg-inner-html-fix'; import { applyTextNodeMergingFix } from '../compat/text-node-merging-fix'; diff --git a/packages/@glimmer/runtime/lib/dom/helper.ts b/packages/@glimmer/runtime/lib/dom/helper.ts index f18f465894..3dab9181c3 100644 --- a/packages/@glimmer/runtime/lib/dom/helper.ts +++ b/packages/@glimmer/runtime/lib/dom/helper.ts @@ -5,8 +5,8 @@ import type { SimpleElement, SimpleNode, } from '@glimmer/interfaces'; +import { NS_SVG } from '@glimmer/constants'; import { castToSimple } from '@glimmer/debug-util'; -import { NS_SVG } from '@glimmer/util'; import { applySVGInnerHTMLFix } from '../compat/svg-inner-html-fix'; import { applyTextNodeMergingFix } from '../compat/text-node-merging-fix'; diff --git a/packages/@glimmer/runtime/lib/dom/operations.ts b/packages/@glimmer/runtime/lib/dom/operations.ts index c5d2c6d6d1..e1bb0886a2 100644 --- a/packages/@glimmer/runtime/lib/dom/operations.ts +++ b/packages/@glimmer/runtime/lib/dom/operations.ts @@ -8,8 +8,8 @@ import type { SimpleNode, SimpleText, } from '@glimmer/interfaces'; +import { INSERT_BEFORE_BEGIN, INSERT_BEFORE_END, NS_SVG } from '@glimmer/constants'; import { expect } from '@glimmer/debug-util'; -import { INSERT_BEFORE_BEGIN, INSERT_BEFORE_END, NS_SVG } from '@glimmer/util'; import { ConcreteBounds } from '../bounds'; diff --git a/packages/@glimmer/runtime/lib/opcodes.ts b/packages/@glimmer/runtime/lib/opcodes.ts index 0fc5ffed1d..b3a55db008 100644 --- a/packages/@glimmer/runtime/lib/opcodes.ts +++ b/packages/@glimmer/runtime/lib/opcodes.ts @@ -7,12 +7,13 @@ import type { VmMachineOp, VmOp, } from '@glimmer/interfaces'; +import { VM_SYSCALL_SIZE } from '@glimmer/constants'; import { debug, logOpcode, opcodeMetadata, recordStackSize } from '@glimmer/debug'; import { assert, unwrap } from '@glimmer/debug-util'; -import { LOCAL_DEBUG, LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_DEBUG, LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import { valueForRef } from '@glimmer/reference'; import { LOCAL_LOGGER } from '@glimmer/util'; -import { $fp, $pc, $ra, $s0, $s1, $sp, $t0, $t1, $v0, Op } from '@glimmer/vm'; +import { $fp, $pc, $ra, $s0, $s1, $sp, $t0, $t1, $v0 } from '@glimmer/vm'; import type { LowLevelVM, VM } from './vm'; @@ -51,7 +52,10 @@ export type DebugState = { }; export class AppendOpcodes { - private evaluateOpcode: Evaluate[] = new Array(Op.Size).fill(null); + private evaluateOpcode: Evaluate[] = new Array(VM_SYSCALL_SIZE).fill(null); + + declare debugBefore?: (vm: VM, opcode: RuntimeOp) => DebugState; + declare debugAfter?: (vm: VM, pre: DebugState) => void; add(name: Name, evaluate: Syscall): void; add(name: Name, evaluate: MachineOpcode, kind: 'machine'): void; @@ -66,111 +70,6 @@ export class AppendOpcodes { } as Evaluate; } - debugBefore(vm: VM, opcode: RuntimeOp): DebugState { - let params: Maybe = undefined; - let opName: string | undefined = undefined; - - if (LOCAL_SHOULD_LOG) { - const lowlevel = unwrap(vm.debug).lowlevel; - let pos = lowlevel.fetchRegister($pc) - opcode.size; - - [opName, params] = debug(vm.constants, opcode, opcode.isMachine)!; - - // console.log(`${typePos(vm['pc'])}.`); - LOCAL_LOGGER.log(`${pos}. ${logOpcode(opName, params)}`); - - let debugParams = []; - for (let prop in params) { - debugParams.push(prop, '=', params[prop]); - } - - LOCAL_LOGGER.log(...debugParams); - } - - let sp: number; - - if (LOCAL_DEBUG) { - sp = vm.fetchValue($sp); - } - - recordStackSize(vm.fetchValue($sp)); - return { - sp: sp!, - pc: vm.fetchValue($pc), - name: opName, - params, - type: opcode.type, - isMachine: opcode.isMachine, - size: opcode.size, - state: undefined, - }; - } - - debugAfter(vm: VM, pre: DebugState) { - let { sp, type, isMachine, pc } = pre; - - if (LOCAL_DEBUG) { - const debug = unwrap(vm.debug); - - let meta = opcodeMetadata(type, isMachine); - let actualChange = vm.fetchValue($sp) - sp; - if ( - meta && - meta.check && - typeof meta.stackChange! === 'number' && - meta.stackChange !== actualChange - ) { - throw new Error( - `Error in ${pre.name}:\n\n${pc}. ${logOpcode( - pre.name!, - pre.params - )}\n\nStack changed by ${actualChange}, expected ${meta.stackChange}` - ); - } - - if (LOCAL_SHOULD_LOG) { - const { lowlevel, registers } = unwrap(vm.debug); - LOCAL_LOGGER.log( - '%c -> pc: %d, ra: %d, fp: %d, sp: %d, s0: %O, s1: %O, t0: %O, t1: %O, v0: %O', - 'color: orange', - lowlevel.registers[$pc], - lowlevel.registers[$ra], - lowlevel.registers[$fp], - lowlevel.registers[$sp], - registers[$s0], - registers[$s1], - registers[$t0], - registers[$t1], - registers[$v0] - ); - LOCAL_LOGGER.log('%c -> eval stack', 'color: red', vm.stack.toArray()); - LOCAL_LOGGER.log('%c -> block stack', 'color: magenta', vm.elements().debugBlocks()); - LOCAL_LOGGER.log( - '%c -> destructor stack', - 'color: violet', - debug.destroyableStack.toArray() - ); - if (debug.stacks.scope.current === null) { - LOCAL_LOGGER.log('%c -> scope', 'color: green', 'null'); - } else { - LOCAL_LOGGER.log( - '%c -> scope', - 'color: green', - vm.scope().slots.map((s) => (isScopeReference(s) ? valueForRef(s) : s)) - ); - } - - LOCAL_LOGGER.log( - '%c -> elements', - 'color: blue', - vm.elements()[CURSOR_STACK].current!.element - ); - - LOCAL_LOGGER.log('%c -> constructing', 'color: aqua', vm.elements()['constructing']); - } - } - } - evaluate(vm: VM, opcode: RuntimeOp, type: number) { let operation = unwrap(this.evaluateOpcode[type]); @@ -190,4 +89,113 @@ export class AppendOpcodes { } } +if (import.meta.env.VM_LOCAL_DEV) { + Object.assign(AppendOpcodes.prototype, { + debugBefore(vm: VM, opcode: RuntimeOp): DebugState { + let params: Maybe = undefined; + let opName: string | undefined = undefined; + + if (LOCAL_TRACE_LOGGING) { + const lowlevel = unwrap(vm.debug).lowlevel; + let pos = lowlevel.fetchRegister($pc) - opcode.size; + + [opName, params] = debug(vm.constants, opcode, opcode.isMachine)!; + + // console.log(`${typePos(vm['pc'])}.`); + LOCAL_LOGGER.debug(`${pos}. ${logOpcode(opName, params)}`); + + let debugParams = []; + for (let prop in params) { + debugParams.push(prop, '=', params[prop]); + } + + LOCAL_LOGGER.debug(...debugParams); + } + + let sp: number; + + if (LOCAL_DEBUG) { + sp = vm.fetchValue($sp); + } + + recordStackSize(vm.fetchValue($sp)); + return { + sp: sp!, + pc: vm.fetchValue($pc), + name: opName, + params, + type: opcode.type, + isMachine: opcode.isMachine, + size: opcode.size, + state: undefined, + }; + }, + + debugAfter(vm: VM, pre: DebugState) { + let { sp, type, isMachine, pc } = pre; + + if (LOCAL_DEBUG) { + const debug = unwrap(vm.debug); + + let meta = opcodeMetadata(type, isMachine); + let actualChange = vm.fetchValue($sp) - sp; + if ( + meta && + meta.check && + typeof meta.stackChange! === 'number' && + meta.stackChange !== actualChange + ) { + throw new Error( + `Error in ${pre.name}:\n\n${pc}. ${logOpcode( + pre.name!, + pre.params + )}\n\nStack changed by ${actualChange}, expected ${meta.stackChange}` + ); + } + + if (LOCAL_TRACE_LOGGING) { + const { lowlevel, registers } = unwrap(vm.debug); + LOCAL_LOGGER.debug( + '%c -> pc: %d, ra: %d, fp: %d, sp: %d, s0: %O, s1: %O, t0: %O, t1: %O, v0: %O', + 'color: orange', + lowlevel.registers[$pc], + lowlevel.registers[$ra], + lowlevel.registers[$fp], + lowlevel.registers[$sp], + registers[$s0], + registers[$s1], + registers[$t0], + registers[$t1], + registers[$v0] + ); + LOCAL_LOGGER.debug('%c -> eval stack', 'color: red', vm.stack.toArray()); + LOCAL_LOGGER.debug('%c -> block stack', 'color: magenta', vm.elements().debugBlocks()); + LOCAL_LOGGER.debug( + '%c -> destructor stack', + 'color: violet', + debug.destroyableStack.toArray() + ); + if (debug.stacks.scope.current === null) { + LOCAL_LOGGER.debug('%c -> scope', 'color: green', 'null'); + } else { + LOCAL_LOGGER.debug( + '%c -> scope', + 'color: green', + vm.scope().slots.map((s) => (isScopeReference(s) ? valueForRef(s) : s)) + ); + } + + LOCAL_LOGGER.debug( + '%c -> elements', + 'color: blue', + vm.elements()[CURSOR_STACK].current!.element + ); + + LOCAL_LOGGER.debug('%c -> constructing', 'color: aqua', vm.elements()['constructing']); + } + } + }, + }); +} + export const APPEND_OPCODES = new AppendOpcodes(); diff --git a/packages/@glimmer/runtime/lib/vm/append.ts b/packages/@glimmer/runtime/lib/vm/append.ts index 5c5ff89038..815d708ac6 100644 --- a/packages/@glimmer/runtime/lib/vm/append.ts +++ b/packages/@glimmer/runtime/lib/vm/append.ts @@ -21,9 +21,11 @@ import type { import type { RuntimeOpImpl } from '@glimmer/program'; import type { OpaqueIterationItem, OpaqueIterator, Reference } from '@glimmer/reference'; import type { + $fp, $ra, $s0, $s1, + $sp, $t0, $t1, $v0, @@ -31,14 +33,14 @@ import type { Register, SyscallRegister, } from '@glimmer/vm'; -import { assert, expect, unwrapHandle } from '@glimmer/debug-util'; +import { expect, unwrapHandle } from '@glimmer/debug-util'; import { associateDestroyableChild } from '@glimmer/destroyable'; import { assertGlobalContextWasSet } from '@glimmer/global-context'; -import { LOCAL_DEBUG, LOCAL_SHOULD_LOG } from '@glimmer/local-debug-flags'; +import { LOCAL_DEBUG, LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; import { createIteratorItemRef, UNDEFINED_REFERENCE } from '@glimmer/reference'; import { LOCAL_LOGGER, reverse, Stack } from '@glimmer/util'; import { beginTrackFrame, endTrackFrame, resetTracking } from '@glimmer/validator'; -import { $fp, $pc, $sp, isLowLevelRegister } from '@glimmer/vm'; +import { $pc, isLowLevelRegister } from '@glimmer/vm'; import type { DebugState } from '../opcodes'; import type { LiveBlockList } from './element-builder'; @@ -52,7 +54,6 @@ import { } from '../compiled/opcodes/vm'; import { APPEND_OPCODES } from '../opcodes'; import { PartialScopeImpl } from '../scope'; -import { REGISTERS } from '../symbols'; import { VMArgumentsImpl } from './arguments'; import { LowLevelVM } from './low-level'; import RenderResultImpl from './render-result'; @@ -194,13 +195,7 @@ export class VM implements PublicVM { } this.resume = initVM(context); - let evalStack = EvaluationStackImpl.restore(stack); - - assert(typeof pc === 'number', 'pc is a number'); - - evalStack[REGISTERS][$pc] = pc; - evalStack[REGISTERS][$sp] = stack.length - 1; - evalStack[REGISTERS][$fp] = -1; + let evalStack = EvaluationStackImpl.restore(stack, pc); this.#heap = this.program.heap; this.constants = this.program.constants; @@ -212,16 +207,18 @@ export class VM implements PublicVM { evalStack, this.#heap, runtime.program, - { - debugBefore: (opcode: RuntimeOpImpl): DebugState => { - return APPEND_OPCODES.debugBefore(this, opcode); - }, - - debugAfter: (state: DebugState): void => { - APPEND_OPCODES.debugAfter(this, state); - }, - }, - evalStack[REGISTERS] + import.meta.env.VM_LOCAL_DEV + ? { + debugBefore: (opcode: RuntimeOpImpl): DebugState => { + return APPEND_OPCODES.debugBefore!(this, opcode); + }, + + debugAfter: (state: DebugState): void => { + APPEND_OPCODES.debugAfter!(this, state); + }, + } + : undefined, + evalStack.registers ); this.#destructor = {}; @@ -506,7 +503,7 @@ export class VM implements PublicVM { } private _execute(initialize?: (vm: this) => void): RenderResult { - if (LOCAL_SHOULD_LOG) { + if (LOCAL_TRACE_LOGGING) { LOCAL_LOGGER.log(`EXECUTING FROM ${this.lowlevel.fetchRegister($pc)}`); } diff --git a/packages/@glimmer/runtime/lib/vm/arguments.ts b/packages/@glimmer/runtime/lib/vm/arguments.ts index 676cd0c268..f576650cf0 100644 --- a/packages/@glimmer/runtime/lib/vm/arguments.ts +++ b/packages/@glimmer/runtime/lib/vm/arguments.ts @@ -18,7 +18,7 @@ import type { } from '@glimmer/interfaces'; import type { Reference } from '@glimmer/reference'; import type { Tag } from '@glimmer/validator'; -import { check, CheckBlockSymbolTable, CheckHandle, CheckOption, CheckOr } from '@glimmer/debug'; +import { check, CheckBlockSymbolTable, CheckHandle, CheckNullable, CheckOr } from '@glimmer/debug'; import { unwrap } from '@glimmer/debug-util'; import { createDebugAliasRef, UNDEFINED_REFERENCE, valueForRef } from '@glimmer/reference'; import { dict, EMPTY_STRING_ARRAY, emptyArray, enumerate } from '@glimmer/util'; @@ -28,7 +28,6 @@ import { $sp } from '@glimmer/vm'; import type { EvaluationStack } from './stack'; import { CheckCompilableBlock, CheckReference, CheckScope } from '../compiled/opcodes/-debug-strip'; -import { REGISTERS } from '../symbols'; /* The calling convention is: @@ -45,7 +44,7 @@ export class VMArgumentsImpl implements VMArguments { public blocks = new BlockArgumentsImpl(); empty(stack: EvaluationStack): this { - let base = stack[REGISTERS][$sp] + 1; + let base = stack.registers[$sp] + 1; this.named.empty(stack, base); this.positional.empty(stack, base); @@ -73,7 +72,7 @@ export class VMArgumentsImpl implements VMArguments { let named = this.named; let namedCount = names.length; - let namedBase = stack[REGISTERS][$sp] - namedCount + 1; + let namedBase = stack.registers[$sp] - namedCount + 1; named.setup(stack, namedBase, namedCount, names, atNames); @@ -114,7 +113,7 @@ export class VMArgumentsImpl implements VMArguments { positional.base += offset; named.base += offset; - stack[REGISTERS][$sp] += offset; + stack.registers[$sp] += offset; } } @@ -424,14 +423,14 @@ export class BlockArgumentsImpl implements BlockArguments { let { base, stack } = this; - let table = check(stack.get(idx * 3, base), CheckOption(CheckBlockSymbolTable)); - let scope = check(stack.get(idx * 3 + 1, base), CheckOption(CheckScope)); + let table = check(stack.get(idx * 3, base), CheckNullable(CheckBlockSymbolTable)); + let scope = check(stack.get(idx * 3 + 1, base), CheckNullable(CheckScope)); let handle = check( stack.get(idx * 3 + 2, base), - CheckOption(CheckOr(CheckHandle, CheckCompilableBlock)) + CheckNullable(CheckOr(CheckHandle, CheckCompilableBlock)) ); - return handle === null ? null : ([handle, scope!, table!] as ScopeBlock); + return handle === null ? null : ([handle, scope, table] as ScopeBlock); } capture(): CapturedBlockArguments { diff --git a/packages/@glimmer/runtime/lib/vm/attributes/dynamic.ts b/packages/@glimmer/runtime/lib/vm/attributes/dynamic.ts index e96010760c..1cd35565e7 100644 --- a/packages/@glimmer/runtime/lib/vm/attributes/dynamic.ts +++ b/packages/@glimmer/runtime/lib/vm/attributes/dynamic.ts @@ -8,9 +8,9 @@ import type { Nullable, SimpleElement, } from '@glimmer/interfaces'; +import { NS_SVG } from '@glimmer/constants'; import { castToBrowser } from '@glimmer/debug-util'; import { warnIfStyleNotTrusted } from '@glimmer/global-context'; -import { NS_SVG } from '@glimmer/util'; import { normalizeStringValue } from '../../dom/normalize'; import { normalizeProperty } from '../../dom/props'; diff --git a/packages/@glimmer/runtime/lib/vm/element-builder.ts b/packages/@glimmer/runtime/lib/vm/element-builder.ts index 24ccdd96e6..ce6d2c5c1a 100644 --- a/packages/@glimmer/runtime/lib/vm/element-builder.ts +++ b/packages/@glimmer/runtime/lib/vm/element-builder.ts @@ -353,6 +353,7 @@ export class NewElementBuilder implements ElementBuilder { } __setProperty(name: string, value: unknown): void { + // eslint-disable-next-line @typescript-eslint/no-explicit-any (this.constructing! as any)[name] = value; } diff --git a/packages/@glimmer/runtime/lib/vm/low-level.ts b/packages/@glimmer/runtime/lib/vm/low-level.ts index 07dcd609be..919b7a051b 100644 --- a/packages/@glimmer/runtime/lib/vm/low-level.ts +++ b/packages/@glimmer/runtime/lib/vm/low-level.ts @@ -1,24 +1,37 @@ import type { Nullable, RuntimeHeap, RuntimeOp, RuntimeProgram } from '@glimmer/interfaces'; import type { MachineRegister } from '@glimmer/vm'; +import { + VM_INVOKE_STATIC_OP, + VM_INVOKE_VIRTUAL_OP, + VM_JUMP_OP, + VM_POP_FRAME_OP, + VM_PUSH_FRAME_OP, + VM_RETURN_OP, + VM_RETURN_TO_OP, +} from '@glimmer/constants'; import { assert } from '@glimmer/debug-util'; import { LOCAL_DEBUG } from '@glimmer/local-debug-flags'; -import { $fp, $pc, $ra, $sp, MachineOp } from '@glimmer/vm'; +import { $fp, $pc, $ra, $sp } from '@glimmer/vm'; import type { VM } from './append'; import { APPEND_OPCODES } from '../opcodes'; export interface LowLevelRegisters { - [MachineRegister.pc]: number; - [MachineRegister.ra]: number; - [MachineRegister.sp]: number; - [MachineRegister.fp]: number; + [$pc]: number; + [$ra]: number; + [$sp]: number; + [$fp]: number; } export function initializeRegisters(): LowLevelRegisters { return [0, -1, 0, 0]; } +export function restoreRegisters(pc: number, sp: number): LowLevelRegisters { + return [pc, -1, sp, 0]; +} + export function initializeRegistersWithSP(sp: number): LowLevelRegisters { return [0, -1, sp, 0]; } @@ -45,7 +58,7 @@ export class LowLevelVM { public stack: VmStack, public heap: RuntimeHeap, public program: RuntimeProgram, - public externs: Externs, + public externs: Externs | undefined, readonly registers: LowLevelRegisters ) {} @@ -135,7 +148,7 @@ export class LowLevelVM { } evaluateOuter(opcode: RuntimeOp, vm: VM) { - if (LOCAL_DEBUG) { + if (LOCAL_DEBUG && this.externs) { let { externs: { debugBefore, debugAfter }, } = this; @@ -157,19 +170,19 @@ export class LowLevelVM { evaluateMachine(opcode: RuntimeOp) { switch (opcode.type) { - case MachineOp.PushFrame: + case VM_PUSH_FRAME_OP: return this.pushFrame(); - case MachineOp.PopFrame: + case VM_POP_FRAME_OP: return this.popFrame(); - case MachineOp.InvokeStatic: + case VM_INVOKE_STATIC_OP: return this.call(opcode.op1); - case MachineOp.InvokeVirtual: + case VM_INVOKE_VIRTUAL_OP: return this.call(this.stack.pop()); - case MachineOp.Jump: + case VM_JUMP_OP: return this.goto(opcode.op1); - case MachineOp.Return: + case VM_RETURN_OP: return this.return(); - case MachineOp.ReturnTo: + case VM_RETURN_TO_OP: return this.returnTo(opcode.op1); } } diff --git a/packages/@glimmer/runtime/lib/vm/rehydrate-builder.ts b/packages/@glimmer/runtime/lib/vm/rehydrate-builder.ts index be64474c46..00e7218c21 100644 --- a/packages/@glimmer/runtime/lib/vm/rehydrate-builder.ts +++ b/packages/@glimmer/runtime/lib/vm/rehydrate-builder.ts @@ -12,8 +12,8 @@ import type { SimpleText, } from '@glimmer/interfaces'; import type { Stack } from '@glimmer/util'; +import { COMMENT_NODE, ELEMENT_NODE, NS_SVG, TEXT_NODE } from '@glimmer/constants'; import { assert, castToBrowser, castToSimple, expect } from '@glimmer/debug-util'; -import { COMMENT_NODE, ELEMENT_NODE, NS_SVG, TEXT_NODE } from '@glimmer/util'; import { ConcreteBounds, CursorImpl } from '../bounds'; import { CURSOR_STACK, NewElementBuilder, RemoteLiveBlock } from './element-builder'; diff --git a/packages/@glimmer/runtime/lib/vm/stack.ts b/packages/@glimmer/runtime/lib/vm/stack.ts index 0fc3b0b40c..4357de7356 100644 --- a/packages/@glimmer/runtime/lib/vm/stack.ts +++ b/packages/@glimmer/runtime/lib/vm/stack.ts @@ -1,17 +1,16 @@ -import type { MachineRegister } from '@glimmer/vm'; +import { assert } from '@glimmer/debug-util'; import { LOCAL_DEBUG } from '@glimmer/local-debug-flags'; -import { $fp, $sp } from '@glimmer/vm'; +import { $fp, $pc, $sp } from '@glimmer/vm'; import type { LowLevelRegisters } from './low-level'; -import { REGISTERS } from '../symbols'; import { initializeRegistersWithSP } from './low-level'; export interface EvaluationStack { - [REGISTERS]: LowLevelRegisters; + readonly registers: LowLevelRegisters; push(value: unknown): void; - dup(position?: MachineRegister): void; + dup(position?: number): void; copy(from: number, to: number): void; pop(n?: number): T; peek(offset?: number): T; @@ -24,18 +23,26 @@ export interface EvaluationStack { } export default class EvaluationStackImpl implements EvaluationStack { - static restore(snapshot: unknown[]): EvaluationStackImpl { - return new this(snapshot.slice(), initializeRegistersWithSP(snapshot.length - 1)); + static restore(snapshot: unknown[], pc: number): EvaluationStackImpl { + const stack = new this(snapshot.slice(), initializeRegistersWithSP(snapshot.length - 1)); + + assert(typeof pc === 'number', 'pc is a number'); + + stack.registers[$pc] = pc; + stack.registers[$sp] = snapshot.length - 1; + stack.registers[$fp] = -1; + + return stack; } - readonly [REGISTERS]: LowLevelRegisters; + readonly registers: LowLevelRegisters; // fp -> sp constructor( private stack: unknown[] = [], registers: LowLevelRegisters ) { - this[REGISTERS] = registers; + this.registers = registers; if (LOCAL_DEBUG) { Object.seal(this); @@ -43,11 +50,11 @@ export default class EvaluationStackImpl implements EvaluationStack { } push(value: unknown): void { - this.stack[++this[REGISTERS][$sp]] = value; + this.stack[++this.registers[$sp]] = value; } - dup(position = this[REGISTERS][$sp]): void { - this.stack[++this[REGISTERS][$sp]] = this.stack[position]; + dup(position = this.registers[$sp]): void { + this.stack[++this.registers[$sp]] = this.stack[position]; } copy(from: number, to: number): void { @@ -55,20 +62,20 @@ export default class EvaluationStackImpl implements EvaluationStack { } pop(n = 1): T { - let top = this.stack[this[REGISTERS][$sp]] as T; - this[REGISTERS][$sp] -= n; + let top = this.stack[this.registers[$sp]] as T; + this.registers[$sp] -= n; return top; } peek(offset = 0): T { - return this.stack[this[REGISTERS][$sp] - offset] as T; + return this.stack[this.registers[$sp] - offset] as T; } - get(offset: number, base = this[REGISTERS][$fp]): T { + get(offset: number, base = this.registers[$fp]): T { return this.stack[base + offset] as T; } - set(value: unknown, offset: number, base = this[REGISTERS][$fp]) { + set(value: unknown, offset: number, base = this.registers[$fp]) { this.stack[base + offset] = value; } @@ -77,7 +84,7 @@ export default class EvaluationStackImpl implements EvaluationStack { } capture(items: number): unknown[] { - let end = this[REGISTERS][$sp] + 1; + let end = this.registers[$sp] + 1; let start = end - items; return this.stack.slice(start, end); } @@ -87,6 +94,6 @@ export default class EvaluationStackImpl implements EvaluationStack { } toArray() { - return this.stack.slice(this[REGISTERS][$fp], this[REGISTERS][$sp] + 1); + return this.stack.slice(this.registers[$fp], this.registers[$sp] + 1); } } diff --git a/packages/@glimmer/runtime/package.json b/packages/@glimmer/runtime/package.json index 195836418b..2135c2aadd 100644 --- a/packages/@glimmer/runtime/package.json +++ b/packages/@glimmer/runtime/package.json @@ -54,6 +54,7 @@ }, "devDependencies": { "@glimmer-workspace/build-support": "workspace:*", + "@glimmer/constants": "workspace:*", "@glimmer/debug": "workspace:*", "@glimmer/debug-util": "workspace:*", "@glimmer/local-debug-flags": "workspace:*", diff --git a/packages/@glimmer/syntax/lib/generation/util.ts b/packages/@glimmer/syntax/lib/generation/util.ts index ffaf637e9f..e72c0c3d1a 100644 --- a/packages/@glimmer/syntax/lib/generation/util.ts +++ b/packages/@glimmer/syntax/lib/generation/util.ts @@ -1,13 +1,12 @@ -/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */ import type * as ASTv1 from '../v1/api'; -const enum Char { - NBSP = 0xa0, - QUOT = 0x22, - LT = 0x3c, - GT = 0x3e, - AMP = 0x26, -} +const Char = { + NBSP: 0xa0, + QUOT: 0x22, + LT: 0x3c, + GT: 0x3e, + AMP: 0x26, +}; const ATTR_VALUE_REGEX_TEST = /["&\xA0]/u; const ATTR_VALUE_REGEX_REPLACE = new RegExp(ATTR_VALUE_REGEX_TEST.source, 'gu'); diff --git a/packages/@glimmer/syntax/lib/source/loc/kinds.ts b/packages/@glimmer/syntax/lib/source/loc/kinds.ts index eac96366c0..1822ff9947 100644 --- a/packages/@glimmer/syntax/lib/source/loc/kinds.ts +++ b/packages/@glimmer/syntax/lib/source/loc/kinds.ts @@ -1,31 +1,45 @@ -export enum OffsetKind { - /** - * We have already computed the character position of this offset or span. - */ - CharPosition = 'CharPosition', +/** + * We have already computed the character position of this offset or span. + */ +export type CharOffsetKind = 'CharPosition'; +export const CHAR_OFFSET_KIND: CharOffsetKind = 'CharPosition'; +/** + * This offset or span was instantiated with a Handlebars SourcePosition or SourceLocation. Its + * character position will be computed on demand. + */ +export type HbsPositionKind = 'HbsPosition'; +export const HBS_POSITION_KIND: HbsPositionKind = 'HbsPosition'; +/** + * for (rare) situations where a node is created but there was no source location (e.g. the name + * "default" in default blocks when the word "default" never appeared in source). This is used + * by the internals when there is a legitimate reason for the internals to synthesize a node + * with no location. + */ +export type InternalSyntheticKind = 'InternalsSynthetic'; +export const INTERNAL_SYNTHETIC_KIND: InternalSyntheticKind = 'InternalsSynthetic'; - /** - * This offset or span was instantiated with a Handlebars SourcePosition or SourceLocation. Its - * character position will be computed on demand. - */ - HbsPosition = 'HbsPosition', +/** + * For situations where a node represents zero parts of the source (for example, empty arguments). + * In general, we attempt to assign these nodes *some* position (empty arguments can be + * positioned immediately after the callee), but it's not always possible + */ +export type NonExistentKind = 'NonExistent'; +export const NON_EXISTENT_KIND: NonExistentKind = 'NonExistent'; - /** - * for (rare) situations where a node is created but there was no source location (e.g. the name - * "default" in default blocks when the word "default" never appeared in source). This is used - * by the internals when there is a legitimate reason for the internals to synthesize a node - * with no location. - */ - InternalsSynthetic = 'InternalsSynthetic', - /** - * For situations where a node represents zero parts of the source (for example, empty arguments). - * In general, we attempt to assign these nodes *some* position (empty arguments can be - * positioned immediately after the callee), but it's not always possible - */ - NonExistent = 'NonExistent', - /** - * For situations where a source location was expected, but it didn't correspond to the node in - * the source. This happens if a plugin creates broken locations. - */ - Broken = 'Broken', +/** + * For situations where a source location was expected, but it didn't correspond to the node in + * the source. This happens if a plugin creates broken locations. + */ +export type BrokenKind = 'Broken'; +export const BROKEN_KIND: BrokenKind = 'Broken'; + +export type OffsetKind = CharOffsetKind | HbsPositionKind | InvisibleKind; + +/** + * These kinds describe spans that don't have a concrete location in the original source. + */ +export type InvisibleKind = BrokenKind | InternalSyntheticKind | NonExistentKind; + +export function isInvisible(kind: OffsetKind): kind is InvisibleKind { + return kind !== CHAR_OFFSET_KIND && kind !== HBS_POSITION_KIND; } diff --git a/packages/@glimmer/syntax/lib/source/loc/match.ts b/packages/@glimmer/syntax/lib/source/loc/match.ts index bf288768d3..e94c1d8044 100644 --- a/packages/@glimmer/syntax/lib/source/loc/match.ts +++ b/packages/@glimmer/syntax/lib/source/loc/match.ts @@ -1,8 +1,9 @@ import { assert, isPresentArray } from '@glimmer/debug-util'; +import type { CharOffsetKind, HbsPositionKind, OffsetKind } from './kinds'; import type { CharPosition, HbsPosition, InvisiblePosition, PositionData } from './offset'; -import { OffsetKind } from './kinds'; +import { BROKEN_KIND, INTERNAL_SYNTHETIC_KIND, NON_EXISTENT_KIND } from './kinds'; /** * This file implements the DSL used by span and offset in places where they need to exhaustively @@ -141,23 +142,23 @@ class Matcher { // checking so that matchers can ensure they've actually covered all the cases (and TypeScript // will treat it as an exhaustive match). when( - left: OffsetKind.CharPosition, - right: OffsetKind.HbsPosition, + left: CharOffsetKind, + right: HbsPositionKind, callback: (left: CharPosition, right: HbsPosition) => Out ): ExhaustiveCheck; when( - left: OffsetKind.HbsPosition, - right: OffsetKind.CharPosition, + left: HbsPositionKind, + right: CharOffsetKind, callback: (left: HbsPosition, right: CharPosition) => Out ): ExhaustiveCheck; when( - left: OffsetKind.HbsPosition, - right: OffsetKind.HbsPosition, + left: HbsPositionKind, + right: HbsPositionKind, callback: (left: HbsPosition, right: HbsPosition) => Out ): ExhaustiveCheck; when( - left: OffsetKind.CharPosition, - right: OffsetKind.CharPosition, + left: CharOffsetKind, + right: CharOffsetKind, callback: (left: CharPosition, right: CharPosition) => Out ): ExhaustiveCheck; when( @@ -190,9 +191,9 @@ class Matcher { function patternFor(kind: OffsetKind): Pattern { switch (kind) { - case OffsetKind.Broken: - case OffsetKind.InternalsSynthetic: - case OffsetKind.NonExistent: + case BROKEN_KIND: + case INTERNAL_SYNTHETIC_KIND: + case NON_EXISTENT_KIND: return IsInvisible; default: return kind; diff --git a/packages/@glimmer/syntax/lib/source/loc/offset.ts b/packages/@glimmer/syntax/lib/source/loc/offset.ts index d864784fb2..9b68fdbf60 100644 --- a/packages/@glimmer/syntax/lib/source/loc/offset.ts +++ b/packages/@glimmer/syntax/lib/source/loc/offset.ts @@ -1,9 +1,10 @@ import type { SourcePosition } from '../location'; import type { Source } from '../source'; +import type { BrokenKind, InternalSyntheticKind, NonExistentKind, OffsetKind } from './kinds'; import type { SourceSpan } from './span'; import { UNKNOWN_POSITION } from '../location'; -import { OffsetKind } from './kinds'; +import { BROKEN_KIND, CHAR_OFFSET_KIND, HBS_POSITION_KIND } from './kinds'; import { match, MatchAny } from './match'; import { span } from './span'; @@ -53,7 +54,7 @@ export class SourceOffset { * any part of the source. */ static broken(pos: SourcePosition = UNKNOWN_POSITION): SourceOffset { - return new InvisiblePosition(OffsetKind.Broken, pos).wrap(); + return new InvisiblePosition(BROKEN_KIND, pos).wrap(); } constructor(readonly data: PositionData & AnyPosition) {} @@ -130,7 +131,7 @@ export class SourceOffset { } export class CharPosition implements PositionData { - readonly kind = OffsetKind.CharPosition; + readonly kind = CHAR_OFFSET_KIND; /** Computed from char offset */ _locPos: HbsPosition | BROKEN | null = null; @@ -193,7 +194,7 @@ export class CharPosition implements PositionData { } export class HbsPosition implements PositionData { - readonly kind = OffsetKind.HbsPosition; + readonly kind = HBS_POSITION_KIND; _charPos: CharPosition | BROKEN | null; @@ -251,7 +252,7 @@ export class HbsPosition implements PositionData { export class InvisiblePosition implements PositionData { constructor( - readonly kind: OffsetKind.Broken | OffsetKind.InternalsSynthetic | OffsetKind.NonExistent, + readonly kind: BrokenKind | InternalSyntheticKind | NonExistentKind, // whatever was provided, possibly broken readonly pos: SourcePosition ) {} @@ -291,24 +292,24 @@ export class InvisiblePosition implements PositionData { const eql = match((m) => m .when( - OffsetKind.HbsPosition, - OffsetKind.HbsPosition, + HBS_POSITION_KIND, + HBS_POSITION_KIND, ({ hbsPos: left }, { hbsPos: right }) => left.column === right.column && left.line === right.line ) .when( - OffsetKind.CharPosition, - OffsetKind.CharPosition, + CHAR_OFFSET_KIND, + CHAR_OFFSET_KIND, ({ charPos: left }, { charPos: right }) => left === right ) .when( - OffsetKind.CharPosition, - OffsetKind.HbsPosition, + CHAR_OFFSET_KIND, + HBS_POSITION_KIND, ({ offset: left }, right) => left === right.toCharPos()?.offset ) .when( - OffsetKind.HbsPosition, - OffsetKind.CharPosition, + HBS_POSITION_KIND, + CHAR_OFFSET_KIND, (left, { offset: right }) => left.toCharPos()?.offset === right ) .when(MatchAny, MatchAny, () => false) diff --git a/packages/@glimmer/syntax/lib/source/loc/span.ts b/packages/@glimmer/syntax/lib/source/loc/span.ts index 627de87a77..dd6aa0c9ce 100644 --- a/packages/@glimmer/syntax/lib/source/loc/span.ts +++ b/packages/@glimmer/syntax/lib/source/loc/span.ts @@ -3,12 +3,20 @@ import { assertNever } from '@glimmer/util'; import type { SourceLocation, SourcePosition } from '../location'; import type { Source } from '../source'; +import type { BrokenKind, InvisibleKind, NonExistentKind, OffsetKind } from './kinds'; import type { MatchFn } from './match'; import type { AnyPosition, SourceOffset } from './offset'; import { BROKEN_LOCATION, NON_EXISTENT_LOCATION } from '../location'; import { SourceSlice } from '../slice'; -import { OffsetKind } from './kinds'; +import { + BROKEN_KIND, + CHAR_OFFSET_KIND, + HBS_POSITION_KIND, + INTERNAL_SYNTHETIC_KIND, + isInvisible, + NON_EXISTENT_KIND, +} from './kinds'; import { IsInvisible, match, MatchAny } from './match'; import { BROKEN, CharPosition, HbsPosition, InvisiblePosition } from './offset'; @@ -95,7 +103,7 @@ interface SpanData { */ export class SourceSpan implements SourceLocation { static get NON_EXISTENT(): SourceSpan { - return new InvisibleSpan(OffsetKind.NonExistent, NON_EXISTENT_LOCATION).wrap(); + return new InvisibleSpan(NON_EXISTENT_KIND, NON_EXISTENT_LOCATION).wrap(); } static load(source: Source, serialized: SerializedSourceSpan): SourceSpan { @@ -105,9 +113,9 @@ export class SourceSpan implements SourceLocation { return SourceSpan.synthetic(serialized); } else if (Array.isArray(serialized)) { return SourceSpan.forCharPositions(source, serialized[0], serialized[1]); - } else if (serialized === OffsetKind.NonExistent) { + } else if (serialized === NON_EXISTENT_KIND) { return SourceSpan.NON_EXISTENT; - } else if (serialized === OffsetKind.Broken) { + } else if (serialized === BROKEN_KIND) { return SourceSpan.broken(BROKEN_LOCATION); } @@ -128,18 +136,17 @@ export class SourceSpan implements SourceLocation { } static synthetic(chars: string): SourceSpan { - return new InvisibleSpan(OffsetKind.InternalsSynthetic, NON_EXISTENT_LOCATION, chars).wrap(); + return new InvisibleSpan(INTERNAL_SYNTHETIC_KIND, NON_EXISTENT_LOCATION, chars).wrap(); } static broken(pos: SourceLocation = BROKEN_LOCATION): SourceSpan { - return new InvisibleSpan(OffsetKind.Broken, pos).wrap(); + return new InvisibleSpan(BROKEN_KIND, pos).wrap(); } readonly isInvisible: boolean; constructor(private data: SpanData & AnySpan) { - this.isInvisible = - data.kind !== OffsetKind.CharPosition && data.kind !== OffsetKind.HbsPosition; + this.isInvisible = isInvisible(data.kind); } getStart(): SourceOffset { @@ -301,9 +308,9 @@ export class SourceSpan implements SourceLocation { type AnySpan = HbsSpan | CharPositionSpan | InvisibleSpan; class CharPositionSpan implements SpanData { - readonly kind = OffsetKind.CharPosition; + readonly kind = CHAR_OFFSET_KIND; - _locPosSpan: HbsSpan | BROKEN | null = null; + #locPosSpan: HbsSpan | BROKEN | null = null; constructor( readonly source: Source, @@ -340,16 +347,16 @@ class CharPositionSpan implements SpanData { } toHbsSpan(): HbsSpan | null { - let locPosSpan = this._locPosSpan; + let locPosSpan = this.#locPosSpan; if (locPosSpan === null) { const start = this.charPositions.start.toHbsPos(); const end = this.charPositions.end.toHbsPos(); if (start === null || end === null) { - locPosSpan = this._locPosSpan = BROKEN; + locPosSpan = this.#locPosSpan = BROKEN; } else { - locPosSpan = this._locPosSpan = new HbsSpan(this.source, { + locPosSpan = this.#locPosSpan = new HbsSpan(this.source, { start, end, }); @@ -378,24 +385,24 @@ class CharPositionSpan implements SpanData { } export class HbsSpan implements SpanData { - readonly kind = OffsetKind.HbsPosition; + readonly kind = HBS_POSITION_KIND; - _charPosSpan: CharPositionSpan | BROKEN | null = null; + #charPosSpan: CharPositionSpan | BROKEN | null = null; // the source location from Handlebars + AST Plugins -- could be wrong - _providedHbsLoc: SourceLocation | null; + #providedHbsLoc: SourceLocation | null; constructor( readonly source: Source, readonly hbsPositions: { start: HbsPosition; end: HbsPosition }, providedHbsLoc: SourceLocation | null = null ) { - this._providedHbsLoc = providedHbsLoc; + this.#providedHbsLoc = providedHbsLoc; } serialize(): SerializedConcreteSourceSpan { const charPos = this.toCharPosSpan(); - return charPos === null ? OffsetKind.Broken : charPos.wrap().serialize(); + return charPos === null ? BROKEN_KIND : charPos.wrap().serialize(); } wrap(): SourceSpan { @@ -403,13 +410,13 @@ export class HbsSpan implements SpanData { } private updateProvided(pos: SourcePosition, edge: 'start' | 'end') { - if (this._providedHbsLoc) { - this._providedHbsLoc[edge] = pos; + if (this.#providedHbsLoc) { + this.#providedHbsLoc[edge] = pos; } // invalidate computed character offsets - this._charPosSpan = null; - this._providedHbsLoc = { + this.#charPosSpan = null; + this.#providedHbsLoc = { start: pos, end: pos, }; @@ -456,19 +463,19 @@ export class HbsSpan implements SpanData { } toCharPosSpan(): CharPositionSpan | null { - let charPosSpan = this._charPosSpan; + let charPosSpan = this.#charPosSpan; if (charPosSpan === null) { const start = this.hbsPositions.start.toCharPos(); const end = this.hbsPositions.end.toCharPos(); if (start && end) { - charPosSpan = this._charPosSpan = new CharPositionSpan(this.source, { + charPosSpan = this.#charPosSpan = new CharPositionSpan(this.source, { start, end, }); } else { - charPosSpan = this._charPosSpan = BROKEN; + charPosSpan = this.#charPosSpan = BROKEN; return null; } } @@ -479,7 +486,7 @@ export class HbsSpan implements SpanData { class InvisibleSpan implements SpanData { constructor( - readonly kind: OffsetKind.Broken | OffsetKind.InternalsSynthetic | OffsetKind.NonExistent, + readonly kind: InvisibleKind, // whatever was provided, possibly broken readonly loc: SourceLocation, // if the span represents a synthetic string @@ -488,10 +495,10 @@ class InvisibleSpan implements SpanData { serialize(): SerializedConcreteSourceSpan { switch (this.kind) { - case OffsetKind.Broken: - case OffsetKind.NonExistent: + case BROKEN_KIND: + case NON_EXISTENT_KIND: return this.kind; - case OffsetKind.InternalsSynthetic: + case INTERNAL_SYNTHETIC_KIND: return this.string || ''; } } @@ -542,32 +549,32 @@ class InvisibleSpan implements SpanData { export const span: MatchFn = match((m) => m - .when(OffsetKind.HbsPosition, OffsetKind.HbsPosition, (left, right) => + .when(HBS_POSITION_KIND, HBS_POSITION_KIND, (left, right) => new HbsSpan(left.source, { start: left, end: right, }).wrap() ) - .when(OffsetKind.CharPosition, OffsetKind.CharPosition, (left, right) => + .when(CHAR_OFFSET_KIND, CHAR_OFFSET_KIND, (left, right) => new CharPositionSpan(left.source, { start: left, end: right, }).wrap() ) - .when(OffsetKind.CharPosition, OffsetKind.HbsPosition, (left, right) => { + .when(CHAR_OFFSET_KIND, HBS_POSITION_KIND, (left, right) => { const rightCharPos = right.toCharPos(); if (rightCharPos === null) { - return new InvisibleSpan(OffsetKind.Broken, BROKEN_LOCATION).wrap(); + return new InvisibleSpan(BROKEN_KIND, BROKEN_LOCATION).wrap(); } else { return span(left, rightCharPos); } }) - .when(OffsetKind.HbsPosition, OffsetKind.CharPosition, (left, right) => { + .when(HBS_POSITION_KIND, CHAR_OFFSET_KIND, (left, right) => { const leftCharPos = left.toCharPos(); if (leftCharPos === null) { - return new InvisibleSpan(OffsetKind.Broken, BROKEN_LOCATION).wrap(); + return new InvisibleSpan(BROKEN_KIND, BROKEN_LOCATION).wrap(); } else { return span(leftCharPos, right); } @@ -583,7 +590,4 @@ export type SerializedConcreteSourceSpan = | /** normal */ [start: number, size: number] | /** synthetic */ string; -export type SerializedSourceSpan = - | SerializedConcreteSourceSpan - | OffsetKind.NonExistent - | OffsetKind.Broken; +export type SerializedSourceSpan = SerializedConcreteSourceSpan | NonExistentKind | BrokenKind; diff --git a/packages/@glimmer/syntax/lib/v2/objects/constants.ts b/packages/@glimmer/syntax/lib/v2/objects/constants.ts new file mode 100644 index 0000000000..5c47a029e8 --- /dev/null +++ b/packages/@glimmer/syntax/lib/v2/objects/constants.ts @@ -0,0 +1,10 @@ +/// FreeVarNamespace /// + +export type HELPER_VAR_NS = 'Helper'; +export const HELPER_VAR_NS: HELPER_VAR_NS = 'Helper'; +export type MODIFIER_VAR_NS = 'Modifier'; +export const MODIFIER_VAR_NS: MODIFIER_VAR_NS = 'Modifier'; +export type COMPONENT_VAR_NS = 'Component'; +export const COMPONENT_VAR_NS: COMPONENT_VAR_NS = 'Component'; + +export type FreeVarNamespace = HELPER_VAR_NS | MODIFIER_VAR_NS | COMPONENT_VAR_NS; diff --git a/packages/@glimmer/syntax/lib/v2/objects/resolution.ts b/packages/@glimmer/syntax/lib/v2/objects/resolution.ts index a13317a976..6be6345ddd 100644 --- a/packages/@glimmer/syntax/lib/v2/objects/resolution.ts +++ b/packages/@glimmer/syntax/lib/v2/objects/resolution.ts @@ -8,6 +8,10 @@ import type { GetContextualFreeOpcode } from '@glimmer/interfaces'; import { SexpOpcodes } from '@glimmer/wire-format'; +import type { FreeVarNamespace } from './constants'; + +import { COMPONENT_VAR_NS, HELPER_VAR_NS, MODIFIER_VAR_NS } from './constants'; + /** * Strict resolution is used: * @@ -67,7 +71,7 @@ export class LooseModeResolution { * ^ In either case, `x` should be resolved in the `component` and `helper` namespaces. */ static append(): LooseModeResolution { - return new LooseModeResolution([FreeVarNamespace.Component, FreeVarNamespace.Helper]); + return new LooseModeResolution([COMPONENT_VAR_NS, HELPER_VAR_NS]); } /** @@ -85,7 +89,7 @@ export class LooseModeResolution { * ^ In either case, `x` should be resolved in the `helper` namespace. */ static trustingAppend(): LooseModeResolution { - return this.namespaced(FreeVarNamespace.Helper); + return this.namespaced(HELPER_VAR_NS); } constructor( @@ -96,11 +100,11 @@ export class LooseModeResolution { resolution(): GetContextualFreeOpcode { if (this.namespaces.length === 1) { switch (this.namespaces[0]) { - case FreeVarNamespace.Helper: + case HELPER_VAR_NS: return SexpOpcodes.GetFreeAsHelperHead; - case FreeVarNamespace.Modifier: + case MODIFIER_VAR_NS: return SexpOpcodes.GetFreeAsModifierHead; - case FreeVarNamespace.Component: + case COMPONENT_VAR_NS: return SexpOpcodes.GetFreeAsComponentHead; } } else { @@ -117,15 +121,9 @@ export class LooseModeResolution { } } -export enum FreeVarNamespace { - Helper = 'Helper', - Modifier = 'Modifier', - Component = 'Component', -} - -export const HELPER_NAMESPACE = FreeVarNamespace.Helper; -export const MODIFIER_NAMESPACE = FreeVarNamespace.Modifier; -export const COMPONENT_NAMESPACE = FreeVarNamespace.Component; +export const HELPER_NAMESPACE = HELPER_VAR_NS; +export const MODIFIER_NAMESPACE = MODIFIER_VAR_NS; +export const COMPONENT_NAMESPACE = COMPONENT_VAR_NS; /** * A `Namespaced` must be resolved in one or more namespaces. @@ -149,10 +147,10 @@ export const COMPONENT_NAMESPACE = FreeVarNamespace.Component; * ^ `x` is resolved in the `modifier` namespace */ type Namespaces = - | [FreeVarNamespace.Helper] - | [FreeVarNamespace.Modifier] - | [FreeVarNamespace.Component] - | [FreeVarNamespace.Component, FreeVarNamespace.Helper]; + | [HELPER_VAR_NS] + | [MODIFIER_VAR_NS] + | [COMPONENT_VAR_NS] + | [COMPONENT_VAR_NS, HELPER_VAR_NS]; export type FreeVarResolution = StrictResolution | HtmlResolution | LooseModeResolution; diff --git a/packages/@glimmer/util/index.ts b/packages/@glimmer/util/index.ts index 2b4871a475..0910cdb718 100644 --- a/packages/@glimmer/util/index.ts +++ b/packages/@glimmer/util/index.ts @@ -2,8 +2,6 @@ export * from './lib/array-utils'; export { dict, isDict, isObject, StackImpl as Stack } from './lib/collections'; export { beginTestSteps, endTestSteps, logStep, verifySteps } from './lib/debug-steps'; export * from './lib/dom'; -export * from './lib/dom-utils'; -export * from './lib/immediate'; export { default as intern } from './lib/intern'; export { isSerializationFirstNode, @@ -17,16 +15,16 @@ export type FIXME = (T & S) | T; /** * This constant exists to make it easier to differentiate normal logs from * errant console.logs. LOCAL_LOGGER should only be used inside a - * LOCAL_SHOULD_LOG check. - *FF - * It does not alleviate the need to check LOCAL_SHOULD_LOG, which is used + * LOCAL_TRACE_LOGGING check. + * + * It does not alleviate the need to check LOCAL_TRACE_LOGGING, which is used * for stripping. */ export const LOCAL_LOGGER = console; /** * This constant exists to make it easier to differentiate normal logs from - * errant console.logs. LOGGER can be used outside of LOCAL_SHOULD_LOG checks, + * errant console.logs. LOGGER can be used outside of LOCAL_TRACE_LOGGING checks, * and is meant to be used in the rare situation where a console.* call is * actually appropriate. */ diff --git a/packages/@glimmer/util/lib/debug-steps.ts b/packages/@glimmer/util/lib/debug-steps.ts index 82f70a40d3..2f8a1d7e01 100644 --- a/packages/@glimmer/util/lib/debug-steps.ts +++ b/packages/@glimmer/util/lib/debug-steps.ts @@ -1,7 +1,9 @@ /// import { assert, expect } from '@glimmer/debug-util'; -import { LOCAL_DEBUG } from '@glimmer/local-debug-flags'; +import { LOCAL_DEBUG, LOCAL_TRACE_LOGGING } from '@glimmer/local-debug-flags'; + +import { LOCAL_LOGGER } from '../index'; export let beginTestSteps: (() => void) | undefined; export let endTestSteps: (() => void) | undefined; @@ -27,6 +29,10 @@ if (LOCAL_DEBUG) { }; logStep = (type: string, step: unknown) => { + if (LOCAL_TRACE_LOGGING) { + LOCAL_LOGGER.log('STEP', type, step); + } + if (LOGGED_STEPS === null) return; let steps = LOGGED_STEPS[type]; diff --git a/packages/@glimmer/util/package.json b/packages/@glimmer/util/package.json index 544683ad3e..5f0c81cbe2 100644 --- a/packages/@glimmer/util/package.json +++ b/packages/@glimmer/util/package.json @@ -44,6 +44,7 @@ }, "devDependencies": { "@glimmer-workspace/build-support": "workspace:*", + "@glimmer/constants": "workspace:*", "@glimmer/debug-util": "workspace:*", "@glimmer/local-debug-flags": "workspace:*", "@types/qunit": "^2.19.9", diff --git a/packages/@glimmer/vm/index.ts b/packages/@glimmer/vm/index.ts index 3c9d22144a..7c1369f983 100644 --- a/packages/@glimmer/vm/index.ts +++ b/packages/@glimmer/vm/index.ts @@ -13,21 +13,6 @@ export { TYPE_MASK, TYPE_SIZE, } from './lib/flags'; -export { isMachineOp, isOp, MachineOp, Op } from './lib/opcodes'; -export { - $fp, - $pc, - $ra, - $s0, - $s1, - $sp, - $t0, - $t1, - $v0, - isLowLevelRegister, - MachineRegister, - type Register, - SavedRegister, - type SyscallRegister, - TemporaryRegister, -} from './lib/registers'; +export type { MachineRegister, Register, SyscallRegister } from './lib/registers'; +export type { SavedRegister, TemporaryRegister } from './lib/registers'; +export { $fp, $pc, $ra, $s0, $s1, $sp, $t0, $t1, $v0, isLowLevelRegister } from './lib/registers'; diff --git a/packages/@glimmer/vm/lib/opcodes.toml b/packages/@glimmer/vm/lib/opcodes.toml index 6648e3ccaa..60b8b67352 100644 --- a/packages/@glimmer/vm/lib/opcodes.toml +++ b/packages/@glimmer/vm/lib/opcodes.toml @@ -1,30 +1,21 @@ [machine.pushf] format = "PushFrame" +operand-stack = [[], ["$ra", "$fp"]] operation = "Push a stack frame" -operand-stack = [ - [], - ["$ra", "$fp"] -] [machine.popf] format = "PopFrame" +operand-stack = [["$ra", "$fp"], []] operation = "Pop a stack frame" skip = true -operand-stack = [ - ["$ra", "$fp"], - [] -] [machine.vcall] format = "InvokeVirtual" +operand-stack = [["Handle"], []] operation = "Evaluate the handle at the top of the stack." -operand-stack = [ - ["Handle"], - [] -] [machine.scall] @@ -38,7 +29,7 @@ operation = "Jump to the specified offset." [machine.ret] -format ="Return" +format = "Return" operation = "Return to the previous frame." skip = true @@ -50,20 +41,14 @@ operation = "Return to a place in the program given an offset" [syscall.ncall] format = ["Helper", "helper:handle"] +operand-stack = [["Reference...", "Arguments"], ["Reference"]] operation = "Evaluate a Helper." -operand-stack = [ - ["Reference...", "Arguments"], - ["Reference"] -] [syscall.dynamiccall] format = ["DynamicHelper"] +operand-stack = [["Reference...", "Reference", "Arguments"], ["Reference"]] operation = "Evaluate a dynamic helper." -operand-stack = [ - ["Reference...", "Reference", "Arguments"], - ["Reference"] -] [syscall.vsargs] @@ -84,163 +69,116 @@ symbol table in the component state at register. [syscall.sbvar] format = ["SetVariable", "symbol:u32"] +operand-stack = [["Reference"], []] operation = """ Bind the variable represented by a symbol from the value at the top of the stack. """ -operand-stack = [ - ["Reference"], - [] -] [syscall.sblock] format = ["SetBlock", "symbol:u32"] +operand-stack = [["symbol-table", "scope", "block"], []] operation = "Bind the block at the top of the stack." -operand-stack = [ - ["symbol-table", "scope", "block"], - [] -] [syscall.symload] format = ["GetVariable", "symbol:u32"] +operand-stack = [[], ["Reference"]] operation = """ Push the contents of the variable represented by a symbol (a positional or named argument) onto the stack. """ -operand-stack = [ - [], - ["Reference"] -] [syscall.getprop] format = ["GetProperty", "property:str"] +operand-stack = [["Reference"], ["Reference"]] operation = """ Pop a Reference from the top of the stack, and push a Reference constructed by `.get(property)`. """ -operand-stack = [ - ["Reference"], - ["Reference"] -] [syscall.blockload] format = ["GetBlock", "block:u32"] -operation = "Push the specified bound block onto the stack." -operand-stack = [ - [], - ["scope-block"] -] notes = "TODO: The three elements on the stack can be null" +operand-stack = [[], ["scope-block"]] +operation = "Push the specified bound block onto the stack." [syscall.blockspread] format = ["SpreadBlock"] +operand-stack = [["scope-block"], ["symbol-table", "scope", "handle"]] operation = "Spread a scope block into three stack elements" -operand-stack = [ - ["scope-block"], - ["symbol-table", "scope", "handle"] -] [syscall.hasblockload] format = ["HasBlock"] +operand-stack = [["block?"], ["bool"]] operation = """ Push TRUE onto the stack if the specified block is bound and FALSE if it is not. """ -operand-stack = [ - ["block?"], - ["bool"] -] [syscall.hasparamsload] format = ["HasBlockParams"] +operand-stack = [["block?", "scope?", "symbol-table?"], ["bool"]] operation = """ Push TRUE onto the stack if the specified block is bound *and* has at least one specified formal parameter, and FALSE otherwise. """ -operand-stack = [ - ["block?", "scope?", "symbol-table?"], - ["bool"] -] [syscall.concat] format = ["Concat", "count:u32"] +operand-stack = [["Reference", "Reference..."], ["Reference"]] operation = """ Pop count `Reference`s off the stack and construct a new ConcatReference from them (in reverse order). """ -operand-stack = [ - ["Reference", "Reference..."], - ["Reference"] -] [syscall.ifinline] format = ["IfInline", "count:u32"] +operand-stack = [["Reference", "Reference", "Reference"], ["Reference"]] operation = """ Inline if expression """ -operand-stack = [ - ["Reference", "Reference", "Reference"], - ["Reference"] -] [syscall.not] format = ["Not", "count:u32"] +operand-stack = [["Reference"], ["Reference"]] operation = """ Inline not expression """ -operand-stack = [ - ["Reference"], - ["Reference"] -] [syscall.rconstload] format = ["Constant", "constant:unknown"] +operand-stack = [[], ["unknown"]] operation = """ Push an Object constant onto the stack that is not a JavaScript primitive. """ -operand-stack = [ - [], - ["unknown"] -] [syscall.rconstrefload] format = ["ConstantReference", "constant:unknown"] +operand-stack = [[], ["Reference"]] operation = """ Push a reference constant onto the stack that is not a JavaScript primitive. """ -operand-stack = [ - [], - ["Reference"] -] [syscall.pconstload] format = ["Primitive", "constant:primitive"] -operation = """ -Wrap a JavaScript primitive in a reference and push it -onto the stack. -""" -operand-stack = [ - [], - ["Primitive"] -] notes = """ The two high bits of the constant reference describe the kind of primitive: @@ -249,34 +187,30 @@ the kind of primitive: 01: string 10: true | false | null | undefined """ +operand-stack = [[], ["Primitive"]] +operation = """ +Wrap a JavaScript primitive in a reference and push it +onto the stack. +""" [syscall.ptoref] -format ="PrimitiveReference" +format = "PrimitiveReference" +operand-stack = [["Primitive"], ["Reference"]] operation = "Convert the top of the stack into a primitive reference." -operand-stack = [ - ["Primitive"], - ["Reference"] -] [syscall.reifyload] format = "ReifyU32" -operation = "Convert the top of the stack into a number." -operand-stack = [ - ["Reference"], - ["Reference", "u32"] -] notes = "The Reference represents a u32" +operand-stack = [["Reference"], ["Reference", "u32"]] +operation = "Convert the top of the stack into a number." [syscall.dup] format = ["Dup", "register:u32", "offset:u32"] +operand-stack = [["unknown"], ["unknown", "unknown"]] operation = "Duplicate and push item from an offset in the stack." -operand-stack = [ - ["unknown"], - ["unknown", "unknown"] -] [syscall.pop] @@ -287,47 +221,41 @@ skip = true [syscall.put] format = ["Load", "register:u32"] +operand-stack = [["unknown"], []] operation = "Load a value into a register" -operand-stack = [ - ["unknown"], - [] -] [syscall.regload] format = ["Fetch", "register:u32"] +operand-stack = [[], ["unknown"]] operation = "Fetch a value from a register" -operand-stack = [ - [], - ["unknown"] -] [syscall.rscopepush] format = ["RootScope", "symbols:u32"] -operation = "Push a new root scope onto the scope stack." notes = """ A root scope has no parent scope, and therefore inherits no lexical variables. """ +operation = "Push a new root scope onto the scope stack." [syscall.vrscopepush] format = ["VirtualRootScope", "register:u32"] -operation = "Push a new root scope onto the scope stack." notes = """ The symbol count is determined by the component state in the specified register. """ +operation = "Push a new root scope onto the scope stack." [syscall.cscopepush] format = "ChildScope" -operation = "Push a new child scope onto the scope stack." notes = """ A child scope inherits from the current parent scope, and therefore shares its lexical variables. """ +operation = "Push a new child scope onto the scope stack." [syscall.scopepop] @@ -347,47 +275,32 @@ operation = "Append a Comment node with value `contents`" [syscall.apnd_dynhtml] format = "AppendHTML" +operand-stack = [["Reference"], []] operation = "Append content as HTML." -operand-stack = [ - ["Reference"], - [] -] [syscall.apnd_dynshtml] format = "AppendSafeHTML" +operand-stack = [["Reference"], []] operation = "Append SafeHTML as HTML." -operand-stack = [ - ["Reference"], - [] -] [syscall.apnd_dynfrag] format = "AppendDocumentFragment" +operand-stack = [["Reference"], []] operation = "Append DocumentFragment." -operand-stack = [ - ["Reference"], - [] -] [syscall.apnd_dynnode] format = "AppendNode" +operand-stack = [["Reference"], []] operation = "Append Node." -operand-stack = [ - ["Reference"], - [] -] [syscall.apnd_dyntext] format = "AppendText" +operand-stack = [["Reference"], []] operation = "Append content as text." -operand-stack = [ - ["Reference"], - [] -] [syscall.apnd_tag] @@ -397,23 +310,17 @@ operation = "Open a new Element named `tag`." [syscall.apnd_dyntag] format = "OpenDynamicElement" +operand-stack = [["string"], []] operation = """ Open a new Element with a name on the stack. """ -operand-stack = [ - ["string"], - [] -] [syscall.apnd_remotetag] format = "PushRemoteElement" -operation = "Open a new remote element" -operand-stack = [ - ["Reference", "Reference", "Reference"], - [] -] notes = "the references represent string, node, and element, in order" +operand-stack = [["Reference", "Reference", "Reference"], []] +operation = "Open a new remote element" [syscall.apnd_attr] @@ -423,30 +330,24 @@ operation = "Add an attribute to the current Element." [syscall.apnd_dynattr] format = ["DynamicAttr", "name:str", "trusting:bool", "namespace:option-str"] -operation = """ -Add an attribute to the current element using the value -at the top of the stack. -""" -operand-stack = [ - ["Reference"], - [] -] notes = """ If `trusting` is false, the host may sanitize the attribute based upon known risks. """ +operand-stack = [["Reference"], []] +operation = """ +Add an attribute to the current element using the value +at the top of the stack. +""" [syscall.apnd_cattr] -format =["ComponentAttr", "name:str", "trusting:bool", "namespace:option-str"] +format = ["ComponentAttr", "name:str", "trusting:bool", "namespace:option-str"] +operand-stack = [["Reference"], []] operation = """ Add an attribute to the current element using the value at the top of the stack. """ -operand-stack = [ - ["Reference"], - [] -] [syscall.apnd_flushtag] @@ -466,24 +367,18 @@ operation = "Close the current remote element" [syscall.apnd_modifier] format = ["Modifier", "helper:handle"] +operand-stack = [["Arguments"], []] operation = "Execute the modifier represented by the handle" -operand-stack = [ - ["Arguments"], - [] -] [syscall.setdynscope] format = ["BindDynamicScope", "names:str-array"] -operation = "Bind stack values as dynamic variables." -operand-stack = [ - ["Reference", "Reference..."], - [] -] notes = """ This is used to expose `-with-dynamic-vars`, and is a niche feature. """ +operand-stack = [["Reference", "Reference..."], []] +operation = "Bind stack values as dynamic variables." [syscall.dynscopepush] @@ -498,96 +393,68 @@ operation = "Pop a dynamic scope frame" [syscall.cmpblock] format = "CompileBlock" +operand-stack = [["CompilableBlock"], ["Handle"]] operation = "Compile the InlineBlock at the top of the stack." -operand-stack = [ - ["CompilableBlock"], - ["Handle"] -] [syscall.scopeload] format = ["PushBlockScope", "scope:scope"] +operand-stack = [[], ["scope"]] operation = "Push a scope onto the stack." -operand-stack = [ - [], - ["scope"] -] [syscall.dsymload] format = ["PushSymbolTable", "table:symbol-table"] +operand-stack = [[], ["symbol-table"]] operation = "Push a symbol table onto the stack." -operand-stack = [ - [], - ["symbol-table"] -] [syscall.invokeyield] format = "InvokeYield" +operand-stack = [["Reference...", "Arguments", "symbol-table", "handle"], []] operation = "Yield to a block." -operand-stack = [ - ["Reference...", "Arguments", "symbol-table", "handle"], - [] -] [syscall.iftrue] format = ["JumpIf", "to:u32"] +operand-stack = [["Reference"], []] operation = """ Jump to the specified offset if the value at the top of the stack is true. """ -operand-stack = [ - ["Reference"], - [] -] [syscall.iffalse] format = ["JumpUnless", "to:u32"] +operand-stack = [["Reference"], []] operation = """ Jump to the specified offset if the value at the top of the stack is false. """ -operand-stack = [ - ["Reference"], - [] -] [syscall.ifeq] format = ["JumpEq", "to:i32", "comparison:i32"] +operand-stack = [["u32"], ["u32"]] operation = """ Jump to the specified offset if the value at the top of the stack is the same as the comparison. """ -operand-stack = [ - ["u32"], - ["u32"] -] [syscall.assert_eq] format = "AssertSame" +notes = "The reference is a u32" +operand-stack = [["Reference"], ["Reference"]] operation = """ Validate that the value at the top of the stack hasn't changed. """ -operand-stack = [ - ["Reference"], - ["Reference"] -] -notes = "The reference is a u32" [syscall.blk_start] format = ["Enter", "args:u32"] -operation = """ -Start tracking a new output block that could change -if one of its inputs changes. -""" notes = """ Soon after this opcode, one of Jump, JumpIf, JumpUnless, or JumpEq will produce an updating @@ -597,34 +464,32 @@ to `to` will be executed. TODO: Save and restore. """ +operation = """ +Start tracking a new output block that could change +if one of its inputs changes. +""" [syscall.blk_end] format = "Exit" -operation = "Finish tracking the current block." notes = """ This finalizes the validators that the updating block must check to determine whether it's safe to skip running the contents. """ +operation = "Finish tracking the current block." [syscall.anytobool] format = "ToBoolean" +operand-stack = [["Reference"], ["Reference"]] operation = "Convert the top of the stack into a boolean reference." -operand-stack = [ - ["Reference"], - ["Reference"] -] [syscall.list_start] format = ["EnterList", "address:u32", "address:u32"] +operand-stack = [["Reference", "Reference"], ["Reference..."]] operation = "Enter a list." -operand-stack = [ - ["Reference", "Reference"], - ["Reference..."] -] [syscall.list_end] @@ -634,12 +499,6 @@ operation = "Exit the current list." [syscall.iter] format = ["Iterate", "end:u32"] -skip = true -operation = """ -Set up the stack for iterating for a given key, -or jump to `end` if there is nothing left to -iterate. -""" notes = """ In Form 1, the stack will have (in reverse order): @@ -647,89 +506,78 @@ In Form 1, the stack will have (in reverse order): - the current iterated value - the memoized iterated value """ +operation = """ +Set up the stack for iterating for a given key, +or jump to `end` if there is nothing left to +iterate. +""" +skip = true [syscall.main] format = ["Main", "state:register"] +operand-stack = [["Invocation", "ComponentDefinition"], []] operation = "Test whether a reference contains a component definition." -operand-stack = [ - ["Invocation", "ComponentDefinition"], - [] -] [syscall.ctload] format = "ContentType" -operation = "Push the content type onto the stack." -operand-stack = [ - ["Reference"], - ["Reference", "Reference"] -] notes = "The new reference represents a ContentType" +operand-stack = [["Reference"], ["Reference", "Reference"]] +operation = "Push the content type onto the stack." [syscall.dctload] format = "DynamicContentType" -operation = "Push the content type onto the stack." -operand-stack = [ - ["Reference"], - ["Reference", "Reference"] -] notes = "The new reference represents a DynamicContentType" +operand-stack = [["Reference"], ["Reference", "Reference"]] +operation = "Push the content type onto the stack." [syscall.curry] format = ["Curry", "type:u32", "is-strict:bool"] -operation = "Curry a value of type for a later invocation." -operand-stack = [ - ["Reference", "Reference...", "Arguments"], - ["CurriedComponent"] -] notes = """ TODO: CurriedValue is { Reference, Type, CapturedArguments } """ +operand-stack = [ + [ + "Reference", + "Reference...", + "Arguments", + ], + [ + "CurriedComponent", + ], +] +operation = "Curry a value of type for a later invocation." [syscall.cmload] format = ["PushComponentDefinition", "spec:handle"] -operation = "Push an appropriate ComponentDefinition onto the stack." -operand-stack = [ - [], - ["ComponentDefinition"] -] notes = """ The handle is a handle for a runtime ComponentDefinition. """ +operand-stack = [[], ["ComponentDefinition"]] +operation = "Push an appropriate ComponentDefinition onto the stack." [syscall.dciload] format = "PushDynamicComponentInstance" +operand-stack = [["ComponentDefinition"], ["InitialComponentState"]] operation = """ Pushes the ComponentInstance onto the stack that is used during the invoke. """ -operand-stack = [ - ["ComponentDefinition"], - ["InitialComponentState"] -] [syscall.cdload] format = ["ResolveDynamicComponent", "owner:owner"] +operand-stack = [["Reference"], ["ComponentDefinition"]] operation = "Push a resolved component definition onto the stack" -operand-stack = [ - ["Reference"], - ["ComponentDefinition"] -] [syscall.argsload] format = ["PushArgs", "names:str-array", "block-names:str-array", "flags:u32"] -operation = "Push a user representation of args onto the stack." -operand-stack = [ - ["Reference..."], - ["Reference...", "Arguments"] -] notes = """ This arguments object is only necessary when calling into user-specified hooks. It is meant to be implemented as a @@ -737,30 +585,26 @@ transient proxy that reads into the stack as needed. Holding onto the Arguments after the call has completed is illegal. """ +operand-stack = [["Reference..."], ["Reference...", "Arguments"]] +operation = "Push a user representation of args onto the stack." [syscall.emptyargsload] format = "PushEmptyArgs" +operand-stack = [[], ["Arguments"]] operation = "Push empty args onto the stack" -operand-stack = [ - [], - ["Arguments"] -] [syscall.argspop] format = "PopArgs" -operation = "Pops Arguments from the stack and clears the next N args." -operand-stack = [ - ["Reference...", "Arguments"], - [] -] notes = """ The arguments object contains the information of how many user supplied args the component was invoked with. To clear them from the stack we must pop it from the stack and call `clear` on it to remove the argument values from the stack. """ +operand-stack = [["Reference...", "Arguments"], []] +operation = "Pops Arguments from the stack and clears the next N args." [syscall.argsprep] @@ -771,11 +615,6 @@ skip = true [syscall.argscapture] format = "CaptureArgs" -operation = "Replaces Arguments on the stack with CapturedArguments" -operand-stack = [ - ["Arguments"], - ["CapturedArguments"] -] notes = """ The Arguments object is mutated in place because it is usually consumed immediately after being pushed on to the stack. In @@ -785,17 +624,19 @@ once. In those cases, the CaptureArgs instruction pops an Arguments object off the stack and replaces it with the immutable CapturedArgs snapshot. """ +operand-stack = [["Arguments"], ["CapturedArguments"]] +operation = "Replaces Arguments on the stack with CapturedArguments" [syscall.comp_create] format = ["CreateComponent", "flags:u32", "state:register"] -operation = "Create the component and push it onto the stack." notes = """ Flags: * 0b001: Has a default block * 0b010: Has an else block """ +operation = "Create the component and push it onto the stack." [syscall.comp_dest] @@ -810,29 +651,20 @@ operation = "Push a new ElementOperations for the current component." [syscall.comp_selfload] format = ["GetComponentSelf", "state:register"] +operand-stack = [[], ["Reference"]] operation = "Push the component's `self` onto the stack." -operand-stack = [ - [], - ["Reference"] -] [syscall.comp_tagload] format = ["GetComponentTagName", "state:register"] +operand-stack = [[], ["option-str"]] operation = "Push the component's `tagName` onto the stack." -operand-stack = [ - [], - ["option-str"] -] [syscall.comp_layoutload] format = ["GetComponentLayout", "state:register"] +operand-stack = [[], ["ProgramSymbolTable", "handle"]] operation = "Get the component layout from the manager." -operand-stack = [ - [], - ["ProgramSymbolTable", "handle"] -] [syscall.eval_scope] @@ -847,14 +679,11 @@ operation = "Setup for eval" [syscall.comp_layoutput] format = ["PopulateLayout", "state:register"] +operand-stack = [["ProgramSymbolTable", "handle"], []] operation = """ Populate the state register with the layout currently on the stack. """ -operand-stack = [ - ["ProgramSymbolTable", "handle"], - [] -] [syscall.comp_invokelayout] @@ -864,11 +693,8 @@ operation = "Invoke the layout returned by the manager." [syscall.comp_begin] format = "BeginComponentTransaction" +operand-stack = [["ComponentManager", "T"], ["ComponentManager", "T"]] operation = "Begin a new cache group" -operand-stack = [ - ["ComponentManager", "T"], - ["ComponentManager", "T"] -] [syscall.comp_commit] @@ -885,18 +711,6 @@ operation = "Invoke didCreateElement on the current component manager" format = ["DidRenderLayout", "state:register"] operation = "Invoke didRenderLayout on the current component manager" -[syscall.eval_varload] - -format = ["ResolveMaybeLocal", "local:str"] -operation = """ -Resolve {{foo}} inside a partial, which could be either a self-lookup -or a local variable that is in-scope for the caller. -""" -operand-stack = [ - [], - ["Reference"] -] - [syscall.debugger] format = ["Debugger", "symbols:str-array", "debugInfo:array"] diff --git a/packages/@glimmer/vm/lib/opcodes.ts b/packages/@glimmer/vm/lib/opcodes.ts deleted file mode 100644 index 165c041c4b..0000000000 --- a/packages/@glimmer/vm/lib/opcodes.ts +++ /dev/null @@ -1,226 +0,0 @@ -import type { - VmAppendDocumentFragment, - VmAppendHTML, - VmAppendNode, - VmAppendSafeHTML, - VmAppendText, - VmAssertSame, - VmBeginComponentTransaction, - VmBindDynamicScope, - VmBindEvalScope, - VmCaptureArgs, - VmChildScope, - VmCloseElement, - VmComment, - VmCommitComponentTransaction, - VmCompileBlock, - VmComponentAttr, - VmConcat, - VmConstant, - VmConstantReference, - VmContentType, - VmCreateComponent, - VmCurry, - VmDebugger, - VmDidCreateElement, - VmDidRenderLayout, - VmDup, - VmDynamicAttr, - VmDynamicContentType, - VmDynamicHelper, - VmDynamicModifier, - VmEnter, - VmEnterList, - VmExit, - VmExitList, - VmFetch, - VmFlushElement, - VmGetBlock, - VmGetComponentLayout, - VmGetComponentSelf, - VmGetComponentTagName, - VmGetDynamicVar, - VmGetProperty, - VmGetVariable, - VmHasBlock, - VmHasBlockParams, - VmHelper, - VmIfInline, - VmInvokeComponentLayout, - VmInvokeYield, - VmIterate, - VmJumpEq, - VmJumpIf, - VmJumpUnless, - VmLoad, - VmLog, - VmMachineInvokeStatic, - VmMachineInvokeVirtual, - VmMachineJump, - VmMachineOp, - VmMachinePopFrame, - VmMachinePushFrame, - VmMachineReturn, - VmMachineReturnTo, - VmMachineSize, - VmMain, - VmModifier, - VmNot, - VmOp, - VmOpenDynamicElement, - VmOpenElement, - VmPop, - VmPopArgs, - VmPopDynamicScope, - VmPopRemoteElement, - VmPopScope, - VmPopulateLayout, - VmPrepareArgs, - VmPrimitive, - VmPrimitiveReference, - VmPushArgs, - VmPushBlockScope, - VmPushComponentDefinition, - VmPushDynamicComponentInstance, - VmPushDynamicScope, - VmPushEmptyArgs, - VmPushRemoteElement, - VmPushSymbolTable, - VmPutComponentOperations, - VmRegisterComponentDestructor, - VmReifyU32, - VmResolveCurriedComponent, - VmResolveDynamicComponent, - VmResolveMaybeLocal, - VmRootScope, - VmSetBlock, - VmSetBlocks, - VmSetNamedVariables, - VmSetupForEval, - VmSetVariable, - VmSize, - VmSpreadBlock, - VmStaticAttr, - VmStaticComponentAttr, - VmText, - VmToBoolean, - VmVirtualRootScope, -} from '@glimmer/interfaces'; - -export const MachineOp = { - PushFrame: 0 satisfies VmMachinePushFrame, - PopFrame: 1 satisfies VmMachinePopFrame, - InvokeVirtual: 2 satisfies VmMachineInvokeVirtual, - InvokeStatic: 3 satisfies VmMachineInvokeStatic, - Jump: 4 satisfies VmMachineJump, - Return: 5 satisfies VmMachineReturn, - ReturnTo: 6 satisfies VmMachineReturnTo, - Size: 7 satisfies VmMachineSize, -} as const; - -export const Op = { - Helper: 16 satisfies VmHelper, - SetNamedVariables: 17 satisfies VmSetNamedVariables, - SetBlocks: 18 satisfies VmSetBlocks, - SetVariable: 19 satisfies VmSetVariable, - SetBlock: 20 satisfies VmSetBlock, - GetVariable: 21 satisfies VmGetVariable, - GetProperty: 22 satisfies VmGetProperty, - GetBlock: 23 satisfies VmGetBlock, - SpreadBlock: 24 satisfies VmSpreadBlock, - HasBlock: 25 satisfies VmHasBlock, - HasBlockParams: 26 satisfies VmHasBlockParams, - Concat: 27 satisfies VmConcat, - Constant: 28 satisfies VmConstant, - ConstantReference: 29 satisfies VmConstantReference, - Primitive: 30 satisfies VmPrimitive, - PrimitiveReference: 31 satisfies VmPrimitiveReference, - ReifyU32: 32 satisfies VmReifyU32, - Dup: 33 satisfies VmDup, - Pop: 34 satisfies VmPop, - Load: 35 satisfies VmLoad, - Fetch: 36 satisfies VmFetch, - RootScope: 37 satisfies VmRootScope, - VirtualRootScope: 38 satisfies VmVirtualRootScope, - ChildScope: 39 satisfies VmChildScope, - PopScope: 40 satisfies VmPopScope, - Text: 41 satisfies VmText, - Comment: 42 satisfies VmComment, - AppendHTML: 43 satisfies VmAppendHTML, - AppendSafeHTML: 44 satisfies VmAppendSafeHTML, - AppendDocumentFragment: 45 satisfies VmAppendDocumentFragment, - AppendNode: 46 satisfies VmAppendNode, - AppendText: 47 satisfies VmAppendText, - OpenElement: 48 satisfies VmOpenElement, - OpenDynamicElement: 49 satisfies VmOpenDynamicElement, - PushRemoteElement: 50 satisfies VmPushRemoteElement, - StaticAttr: 51 satisfies VmStaticAttr, - DynamicAttr: 52 satisfies VmDynamicAttr, - ComponentAttr: 53 satisfies VmComponentAttr, - FlushElement: 54 satisfies VmFlushElement, - CloseElement: 55 satisfies VmCloseElement, - PopRemoteElement: 56 satisfies VmPopRemoteElement, - Modifier: 57 satisfies VmModifier, - BindDynamicScope: 58 satisfies VmBindDynamicScope, - PushDynamicScope: 59 satisfies VmPushDynamicScope, - PopDynamicScope: 60 satisfies VmPopDynamicScope, - CompileBlock: 61 satisfies VmCompileBlock, - PushBlockScope: 62 satisfies VmPushBlockScope, - PushSymbolTable: 63 satisfies VmPushSymbolTable, - InvokeYield: 64 satisfies VmInvokeYield, - JumpIf: 65 satisfies VmJumpIf, - JumpUnless: 66 satisfies VmJumpUnless, - JumpEq: 67 satisfies VmJumpEq, - AssertSame: 68 satisfies VmAssertSame, - Enter: 69 satisfies VmEnter, - Exit: 70 satisfies VmExit, - ToBoolean: 71 satisfies VmToBoolean, - EnterList: 72 satisfies VmEnterList, - ExitList: 73 satisfies VmExitList, - Iterate: 74 satisfies VmIterate, - Main: 75 satisfies VmMain, - ContentType: 76 satisfies VmContentType, - Curry: 77 satisfies VmCurry, - PushComponentDefinition: 78 satisfies VmPushComponentDefinition, - PushDynamicComponentInstance: 79 satisfies VmPushDynamicComponentInstance, - ResolveDynamicComponent: 80 satisfies VmResolveDynamicComponent, - ResolveCurriedComponent: 81 satisfies VmResolveCurriedComponent, - PushArgs: 82 satisfies VmPushArgs, - PushEmptyArgs: 83 satisfies VmPushEmptyArgs, - PopArgs: 84 satisfies VmPopArgs, - PrepareArgs: 85 satisfies VmPrepareArgs, - CaptureArgs: 86 satisfies VmCaptureArgs, - CreateComponent: 87 satisfies VmCreateComponent, - RegisterComponentDestructor: 88 satisfies VmRegisterComponentDestructor, - PutComponentOperations: 89 satisfies VmPutComponentOperations, - GetComponentSelf: 90 satisfies VmGetComponentSelf, - GetComponentTagName: 91 satisfies VmGetComponentTagName, - GetComponentLayout: 92 satisfies VmGetComponentLayout, - BindEvalScope: 93 satisfies VmBindEvalScope, - SetupForEval: 94 satisfies VmSetupForEval, - PopulateLayout: 95 satisfies VmPopulateLayout, - InvokeComponentLayout: 96 satisfies VmInvokeComponentLayout, - BeginComponentTransaction: 97 satisfies VmBeginComponentTransaction, - CommitComponentTransaction: 98 satisfies VmCommitComponentTransaction, - DidCreateElement: 99 satisfies VmDidCreateElement, - DidRenderLayout: 100 satisfies VmDidRenderLayout, - ResolveMaybeLocal: 102 satisfies VmResolveMaybeLocal, - Debugger: 103 satisfies VmDebugger, - Size: 104 satisfies VmSize, - StaticComponentAttr: 105 satisfies VmStaticComponentAttr, - DynamicContentType: 106 satisfies VmDynamicContentType, - DynamicHelper: 107 satisfies VmDynamicHelper, - DynamicModifier: 108 satisfies VmDynamicModifier, - IfInline: 109 satisfies VmIfInline, - Not: 110 satisfies VmNot, - GetDynamicVar: 111 satisfies VmGetDynamicVar, - Log: 112 satisfies VmLog, -} as const; - -export function isMachineOp(value: number): value is VmMachineOp { - return value >= 0 && value <= 15; -} - -export function isOp(value: number): value is VmOp { - return value >= 16; -} diff --git a/packages/@glimmer/vm/lib/registers.ts b/packages/@glimmer/vm/lib/registers.ts index 22ac4117ae..51adb04829 100644 --- a/packages/@glimmer/vm/lib/registers.ts +++ b/packages/@glimmer/vm/lib/registers.ts @@ -6,48 +6,41 @@ */ // $0 or $pc (program counter): pointer into `program` for the next insturction; -1 means exit -export const $pc: MachineRegister.pc = 0; +export type $pc = 0; +export const $pc: $pc = 0; // $1 or $ra (return address): pointer into `program` for the return -export const $ra: MachineRegister.ra = 1; +export type $ra = 1; +export const $ra: $ra = 1; // $2 or $fp (frame pointer): pointer into the `evalStack` for the base of the stack -export const $fp: MachineRegister.fp = 2; +export type $fp = 2; +export const $fp: $fp = 2; // $3 or $sp (stack pointer): pointer into the `evalStack` for the top of the stack -export const $sp: MachineRegister.sp = 3; +export type $sp = 3; +export const $sp: $sp = 3; // $4-$5 or $s0-$s1 (saved): callee saved general-purpose registers -export const $s0: SavedRegister.s0 = 4; -export const $s1: SavedRegister.s1 = 5; +export type $s0 = 4; +export const $s0: $s0 = 4; +export type $s1 = 5; +export const $s1: $s1 = 5; // $6-$7 or $t0-$t1 (temporaries): caller saved general-purpose registers -export const $t0: TemporaryRegister.t0 = 6; -export const $t1: TemporaryRegister.t1 = 7; +export type $t0 = 6; +export const $t0: $t0 = 6; +export type $t1 = 7; +export const $t1: $t1 = 7; // $8 or $v0 (return value) +export type $v0 = 8; export const $v0 = 8; -export enum MachineRegister { - // These must be in sync with the computed values - // above, but TypeScript doesn't like it - - 'pc' = 0, - 'ra' = 1, - 'fp' = 2, - 'sp' = 3, -} +export type MachineRegister = $pc | $ra | $fp | $sp; export function isLowLevelRegister( register: Register | MachineRegister ): register is Register & MachineRegister { - // eslint-disable-next-line @typescript-eslint/no-unsafe-enum-comparison return (register as number) <= $sp; } -export enum SavedRegister { - 's0' = 4, - 's1' = 5, -} - -export enum TemporaryRegister { - 't0' = 6, - 't1' = 7, -} +export type SavedRegister = $s0 | $s1; +export type TemporaryRegister = $t0 | $t1; -export type Register = MachineRegister | SavedRegister | TemporaryRegister | typeof $v0; -export type SyscallRegister = SavedRegister | TemporaryRegister | typeof $v0; +export type Register = MachineRegister | SavedRegister | TemporaryRegister | $v0; +export type SyscallRegister = SavedRegister | TemporaryRegister | $v0; diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5b8b1b4382..938bc20086 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -540,6 +540,9 @@ importers: specifier: ^0.5.11 version: 0.5.11 devDependencies: + '@glimmer/constants': + specifier: workspace:* + version: link:../../@glimmer/constants '@glimmer/debug-util': specifier: workspace:* version: link:../../@glimmer/debug-util @@ -593,6 +596,9 @@ importers: '@glimmer-workspace/build-support': specifier: workspace:* version: link:../../@glimmer-workspace/build + '@glimmer/constants': + specifier: workspace:* + version: link:../constants '@glimmer/debug-util': specifier: workspace:* version: link:../debug-util @@ -609,7 +615,7 @@ importers: specifier: ^0.2.5 version: 0.2.5 rollup: - specifier: ^4.5.1 + specifier: ^4.24.3 version: 4.24.3 typescript: specifier: ^5.0.4 @@ -629,6 +635,63 @@ importers: '@glimmer/util': specifier: workspace:* version: link:../../util + devDependencies: + '@glimmer/constants': + specifier: workspace:* + version: link:../../constants + + packages/@glimmer/constants: + dependencies: + '@glimmer/env': + specifier: 0.1.7 + version: 0.1.7 + '@glimmer/interfaces': + specifier: workspace:* + version: link:../interfaces + devDependencies: + '@glimmer-workspace/build-support': + specifier: workspace:* + version: link:../../@glimmer-workspace/build + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util + '@glimmer/local-debug-flags': + specifier: workspace:* + version: link:../local-debug-flags + '@types/qunit': + specifier: ^2.19.9 + version: 2.19.9 + eslint: + specifier: ^8.52.0 + version: 8.54.0 + publint: + specifier: ^0.2.5 + version: 0.2.5 + rollup: + specifier: ^4.5.1 + version: 4.24.3 + typescript: + specifier: ^5.0.4 + version: 5.0.4 + + packages/@glimmer/constants/test: + dependencies: + '@glimmer/env': + specifier: 0.1.7 + version: 0.1.7 + '@glimmer/util': + specifier: workspace:* + version: link:../../util + devDependencies: + '@glimmer/constants': + specifier: workspace:* + version: link:.. + '@glimmer/debug-util': + specifier: workspace:* + version: link:../../debug-util + vite: + specifier: ^5.4.10 + version: 5.4.10(@types/node@20.9.4) packages/@glimmer/debug: dependencies: @@ -645,6 +708,9 @@ importers: '@glimmer-workspace/build-support': specifier: workspace:* version: link:../../@glimmer-workspace/build + '@glimmer/constants': + specifier: workspace:* + version: link:../constants '@glimmer/debug-util': specifier: workspace:* version: link:../debug-util @@ -980,6 +1046,9 @@ importers: '@glimmer-workspace/build-support': specifier: workspace:* version: link:../../@glimmer-workspace/build + '@glimmer/constants': + specifier: workspace:* + version: link:../constants '@glimmer/debug': specifier: workspace:* version: link:../debug @@ -1035,9 +1104,6 @@ importers: packages/@glimmer/program: dependencies: - '@glimmer/debug-util': - specifier: workspace:* - version: link:../debug-util '@glimmer/encoder': specifier: workspace:* version: link:../encoder @@ -1066,6 +1132,12 @@ importers: '@glimmer-workspace/build-support': specifier: workspace:* version: link:../../@glimmer-workspace/build + '@glimmer/constants': + specifier: workspace:* + version: link:../constants + '@glimmer/debug-util': + specifier: workspace:* + version: link:../debug-util '@glimmer/local-debug-flags': specifier: workspace:* version: link:../local-debug-flags @@ -1189,6 +1261,9 @@ importers: '@glimmer-workspace/build-support': specifier: workspace:* version: link:../../@glimmer-workspace/build + '@glimmer/constants': + specifier: workspace:* + version: link:../constants '@glimmer/debug': specifier: workspace:* version: link:../debug @@ -1294,6 +1369,9 @@ importers: '@glimmer-workspace/build-support': specifier: workspace:* version: link:../../@glimmer-workspace/build + '@glimmer/constants': + specifier: workspace:* + version: link:../constants '@glimmer/debug-util': specifier: workspace:* version: link:../debug-util @@ -5303,7 +5381,7 @@ packages: resolution: {integrity: sha512-bEL/yUb/fNNiNTuUz979Z0Yg5L+LzLxGJz8x79lYmR54fmTIb6ob/hNQgkQnIUDWIFjZVQwl9Xs356I6BAMHfw==} engines: {node: '>= 6'} dependencies: - glob: 7.2.0 + glob: 7.2.3 graceful-fs: 4.2.11 lazystream: 1.0.1 lodash.defaults: 4.2.0 @@ -5615,7 +5693,7 @@ packages: engines: {node: '>= 8.0.0'} dependencies: find-babel-config: 1.2.2 - glob: 7.2.0 + glob: 7.2.3 pkg-up: 3.1.0 reselect: 4.1.8 resolve: 1.22.8 @@ -5853,7 +5931,7 @@ packages: dependencies: ansi-align: 3.0.1 camelcase: 7.0.1 - chalk: 5.2.0 + chalk: 5.3.0 cli-boxes: 3.0.0 string-width: 5.1.2 type-fest: 2.19.0 @@ -6374,7 +6452,7 @@ packages: '@npmcli/move-file': 1.1.2 chownr: 2.0.0 fs-minipass: 2.1.0 - glob: 7.2.0 + glob: 7.2.3 infer-owner: 1.0.4 lru-cache: 6.0.0 minipass: 3.3.6 @@ -10162,6 +10240,7 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 + dev: true /glob@7.2.3: resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} @@ -10173,7 +10252,6 @@ packages: minimatch: 3.1.2 once: 1.4.0 path-is-absolute: 1.0.1 - dev: true /glob@8.1.0: resolution: {integrity: sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==} @@ -10241,7 +10319,7 @@ packages: array-union: 2.1.0 dir-glob: 3.0.1 fast-glob: 3.2.12 - glob: 7.2.0 + glob: 7.2.3 ignore: 5.2.4 merge2: 1.4.1 slash: 3.0.0 @@ -12085,7 +12163,7 @@ packages: resolution: {integrity: sha512-l0x2DvrW294C9uDCoQe1VSU4gf529FkSZ6leBl4TiqZH/e+0R7hSfHQBNut2mNygDgHwvYHfFLn6Oxb3VWj2rA==} engines: {node: '>=12'} dependencies: - chalk: 5.2.0 + chalk: 5.3.0 is-unicode-supported: 1.3.0 dev: true @@ -15158,7 +15236,7 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true dependencies: - glob: 7.2.0 + glob: 7.2.3 dev: true /rimraf@2.6.3: @@ -15166,7 +15244,7 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true dependencies: - glob: 7.2.0 + glob: 7.2.3 dev: true /rimraf@3.0.2: @@ -15174,7 +15252,7 @@ packages: deprecated: Rimraf versions prior to v4 are no longer supported hasBin: true dependencies: - glob: 7.2.0 + glob: 7.2.3 /rimraf@5.0.0: resolution: {integrity: sha512-Jf9llaP+RvaEVS5nPShYFhtXIrb3LRKP281ib3So0KkeZKo2wIKyq0Re7TOSwanasA423PSr6CCIL4bP6T040g==} @@ -15623,7 +15701,7 @@ packages: engines: {node: '>=4'} hasBin: true dependencies: - glob: 7.2.0 + glob: 7.2.3 interpret: 1.4.0 rechoir: 0.6.2 dev: true @@ -16428,7 +16506,7 @@ packages: execa: 1.0.0 express: 4.21.1 fireworm: 0.7.2 - glob: 7.2.0 + glob: 7.2.3 http-proxy: 1.18.1 js-yaml: 3.14.1 lodash: 4.17.21 @@ -17213,7 +17291,7 @@ packages: engines: {node: '>=14.16'} dependencies: boxen: 7.1.1 - chalk: 5.2.0 + chalk: 5.3.0 configstore: 6.0.0 has-yarn: 3.0.0 import-lazy: 4.0.0 diff --git a/test/index.html b/test/index.html index d091a20fc2..69e65abaac 100644 --- a/test/index.html +++ b/test/index.html @@ -58,9 +58,9 @@ }); QUnit.config.urlConfig.push({ - id: "enable_local_should_log", - label: "Enable LOCAL_SHOULD_LOG (extra debug logging info)", - tooltip: "Enable LOCAL_SHOULD_LOG (extra debug logging info)", + id: "enable_local_trace_logging", + label: "Enable LOCAL_TRACE_LOGGING (extra debug logging info)", + tooltip: "Enable LOCAL_TRACE_LOGGING (extra debug logging info)", }); QUnit.config.urlConfig.push({ diff --git a/vite.config.mts b/vite.config.mts index f4bf811dfe..dec51f576b 100644 --- a/vite.config.mts +++ b/vite.config.mts @@ -6,9 +6,6 @@ export default defineConfig({ }, mode: 'testing', plugins: [ - /** - * A similar plugin exists for our rollup builds - */ { name: 'define custom import.meta.env', async transform(code) {