Skip to content

Commit

Permalink
Upgrade to TypeScript 4.0
Browse files Browse the repository at this point in the history
This also updates the eslint-typescript packages

TypeScript 4.0 invalidated the way that we were casting SimpleDOM to
browser DOM and vice versa. This commit changes our casting strategy so
that casts go through additional checks that accomodate TypeScript's new
stricter requirements.

In general, this was a good change: it adds some checks to the blind
casts we were making, and caught at least one genuine mistake in our
casts (casting a textarea to input).

However, these checks add some minor overhead and should be unnecessary
in production. This commit structures the casts so they can be stripped
out relatively easily in the future, and we should do so.
  • Loading branch information
wycats authored and rwjblue committed Sep 3, 2020
1 parent 6dea311 commit 88d0dbf
Show file tree
Hide file tree
Showing 25 changed files with 758 additions and 293 deletions.
17 changes: 10 additions & 7 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@
"@glimmer/env": "0.1.7",
"@types/node": "^13.7.4",
"@types/qunit": "^2.0.31",
"@typescript-eslint/eslint-plugin": "^2.20.0",
"@typescript-eslint/parser": "^2.20.0",
"@typescript-eslint/eslint-plugin": "^3.10.0",
"@typescript-eslint/parser": "^3.10.0",
"amd-name-resolver": "^1.3.1",
"auto-dist-tag": "^1.0.0",
"babel-plugin-nukable-import": "^0.4.2",
Expand All @@ -70,17 +70,17 @@
"broccoli-plugin": "^3.1.0",
"broccoli-rollup": "^4.1.1",
"broccoli-source": "^3.0.0",
"broccoli-typescript-compiler": "^5.0.0",
"broccoli-typescript-compiler": "^6.0.0",
"chalk": "^3.0.0",
"dag-map": "^2.0.2",
"ember-cli": "~3.20.0",
"ember-cli-browserstack": "^1.1.0",
"ensure-posix-path": "^1.1.1",
"eslint": "^6.8.0",
"eslint": "^7.7.0",
"eslint-config-prettier": "^6.11.0",
"eslint-plugin-node": "^11.0.0",
"eslint-plugin-node": "^11.1.0",
"eslint-plugin-prettier": "^3.1.4",
"eslint-plugin-qunit": "^4.0.0",
"eslint-plugin-qunit": "^4.3.0",
"execa": "^1.0.0",
"glob": "^7.0.5",
"js-yaml": "^3.10.0",
Expand All @@ -98,7 +98,10 @@
"semver": "^6.3.0",
"testem-failure-only-reporter": "^0.0.1",
"toml": "^3.0.0",
"typescript": "3.7.5"
"typescript": "4.0.2"
},
"resolutions": {
"typescript": "4.0.2"
},
"publishConfig": {
"registry": "https://registry.npmjs.org"
Expand Down
9 changes: 5 additions & 4 deletions packages/@glimmer/benchmark-env/src/benchmark/on-modifier.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { ModifierManager, VMArguments } from '@glimmer/interfaces';
import { Reference, valueForRef } from '@glimmer/reference';
import { cast } from '@glimmer/runtime';
import { createUpdatableTag } from '@glimmer/validator';
import { SimpleElement } from '@simple-dom/interface';

interface OnModifierState {
element: HTMLElement;
element: SimpleElement;
nameRef: Reference<string>;
listenerRef: Reference<EventListener>;
name: string | null;
Expand All @@ -14,7 +15,7 @@ interface OnModifierState {
class OnModifierManager implements ModifierManager<OnModifierState, null> {
create(element: SimpleElement, _: null, args: VMArguments) {
return {
element: element as HTMLElement,
element,
nameRef: args.positional.at(0) as Reference<string>,
listenerRef: args.positional.at(1) as Reference<EventListener>,
name: null,
Expand All @@ -29,13 +30,13 @@ class OnModifierManager implements ModifierManager<OnModifierState, null> {
install(state: OnModifierState) {
const name = valueForRef(state.nameRef);
const listener = valueForRef(state.listenerRef);
state.element.addEventListener(name, listener);
cast(state.element, 'ELEMENT').addEventListener(name, listener);
state.listener = listener;
state.name = name;
}

update(state: OnModifierState) {
const element = state.element;
const element = cast(state.element, 'ELEMENT');
const name = valueForRef(state.nameRef);
const listener = valueForRef(state.listenerRef);
if (name !== state.name || listener !== state.listener) {
Expand Down
4 changes: 2 additions & 2 deletions packages/@glimmer/compiler/lib/template-compiler.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { ExpressionContext } from '@glimmer/interfaces';
import { locationToOffset } from './location';

export interface CompileOptions {
meta?: unknown;
meta?: object;
customizeComponentName?(tag: string): string;
}

Expand Down Expand Up @@ -334,7 +334,7 @@ export default class TemplateCompiler implements Processor<InputOps> {
let name = assertValidHasBlockUsage(path.original, action);
this.hasBlock(name, action);
} else if (isHasBlockParams(path)) {
let name = assertValidHasBlockUsage(path.original, action);
let name = assertValidHasBlockUsage((path as any).original, action);
this.hasBlockParams(name, action);
}
}
Expand Down
6 changes: 3 additions & 3 deletions packages/@glimmer/compiler/test/compiler-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ import { assign, strip } from '@glimmer/util';
QUnit.module('@glimmer/compiler - compiling source to wire format');

function compile(content: string): SerializedTemplate<unknown> {
let parsed = (JSON.parse(
precompile(content, { meta: null })
) as unknown) as SerializedTemplateWithLazyBlock<unknown>;
let parsed = (JSON.parse(precompile(content, {})) as unknown) as SerializedTemplateWithLazyBlock<
unknown
>;
let block = JSON.parse(parsed.block);

return assign({}, parsed, { block });
Expand Down
89 changes: 45 additions & 44 deletions packages/@glimmer/integration-tests/lib/modes/jit/delegate.ts
Original file line number Diff line number Diff line change
@@ -1,64 +1,65 @@
import { PrecompileOptions } from '@glimmer/compiler';
import {
RuntimeContext,
SyntaxCompilationContext,
Environment,
ComponentDefinition,
Cursor,
ElementBuilder,
Dict,
RenderResult,
Option,
Helper,
HandleResult,
DynamicScope,
ComponentDefinition,
ElementBuilder,
Environment,
HandleResult,
Helper,
Option,
RenderResult,
RuntimeContext,
SyntaxCompilationContext,
} from '@glimmer/interfaces';
import { syntaxCompilationContext } from '@glimmer/opcode-compiler';
import { artifacts } from '@glimmer/program';
import { createConstRef, Reference } from '@glimmer/reference';
import {
SimpleDocument,
SimpleElement,
ElementNamespace,
SimpleText,
SimpleDocumentFragment,
} from '@simple-dom/interface';
import { TestJitRegistry } from './registry';
import {
getDynamicVar,
cast,
clientBuilder,
EnvironmentDelegate,
CurriedComponentDefinition,
runtimeContext,
renderSync,
EnvironmentDelegate,
getDynamicVar,
renderComponent,
renderSync,
runtimeContext,
} from '@glimmer/runtime';
import { artifacts } from '@glimmer/program';
import {
registerInternalHelper,
registerStaticTaglessComponent,
registerEmberishCurlyComponent,
registerEmberishGlimmerComponent,
registerModifier,
registerHelper,
registerPartial,
registerTemplate,
componentHelper,
} from './register';
import { ASTPluginBuilder } from '@glimmer/syntax';
import { assign, unwrapTemplate } from '@glimmer/util';
import {
ElementNamespace,
SimpleDocument,
SimpleDocumentFragment,
SimpleElement,
SimpleText,
} from '@simple-dom/interface';
import { preprocess } from '../../compile';
import { TestMacros } from '../../compile/macros';
import JitCompileTimeLookup from './compilation-context';
import TestJitRuntimeResolver from './resolver';
import RenderDelegate, { RenderDelegateOptions } from '../../render-delegate';
import { ComponentKind, ComponentTypes } from '../../components';
import { BasicComponentFactory } from '../../components/basic';
import { EmberishCurlyComponentFactory } from '../../components/emberish-curly';
import { EmberishGlimmerComponentFactory } from '../../components/emberish-glimmer';
import { TestModifierConstructor } from '../../modifiers';
import { UserHelper } from '../../helpers';
import { createConstRef, Reference } from '@glimmer/reference';
import { renderTemplate } from './render';
import { syntaxCompilationContext } from '@glimmer/opcode-compiler';
import { preprocess } from '../../compile';
import { unwrapTemplate, assign } from '@glimmer/util';
import { TestModifierConstructor } from '../../modifiers';
import RenderDelegate, { RenderDelegateOptions } from '../../render-delegate';
import { BaseEnv } from '../env';
import JitCompileTimeLookup from './compilation-context';
import {
componentHelper,
registerEmberishCurlyComponent,
registerEmberishGlimmerComponent,
registerHelper,
registerInternalHelper,
registerModifier,
registerPartial,
registerStaticTaglessComponent,
registerTemplate,
} from './register';
import { TestJitRegistry } from './registry';
import { renderTemplate } from './render';
import TestJitRuntimeResolver from './resolver';

export interface JitTestDelegateContext {
runtime: RuntimeContext;
Expand Down Expand Up @@ -95,7 +96,7 @@ export class JitRenderDelegate implements RenderDelegate {
private env: EnvironmentDelegate;

constructor(options?: RenderDelegateOptions) {
this.doc = options?.doc ?? (document as SimpleDocument);
this.doc = options?.doc ?? cast(document).simple;
this.env = assign(options?.env ?? {}, BaseEnv);
this.context = this.getContext();
}
Expand All @@ -106,7 +107,7 @@ export class JitRenderDelegate implements RenderDelegate {

getInitialElement(): SimpleElement {
if (isBrowserTestDocument(this.doc)) {
return this.doc.getElementById('qunit-fixture')! as SimpleElement;
return cast(this.doc).getElementById('qunit-fixture');
} else {
return this.createElement('div');
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
import { RehydrateBuilder } from '@glimmer/runtime';
import { SimpleNode } from '@simple-dom/interface';
import { NodeType, SimpleNode } from '@simple-dom/interface';
import { Environment, Cursor, ElementBuilder } from '@glimmer/interfaces';

export class DebugRehydrationBuilder extends RehydrateBuilder {
clearedNodes: SimpleNode[] = [];

remove(node: SimpleNode) {
let next = super.remove(node);
let el = node as Element;

if (node.nodeType !== 8) {
if (el.nodeType === 1) {
if (node.nodeType !== NodeType.COMMENT_NODE) {
if (node.nodeType === NodeType.ELEMENT_NODE) {
// don't stat serialized cursor positions
if (el.tagName !== 'SCRIPT' || !el.getAttribute('glmr')) {
if (node.tagName !== 'SCRIPT' || !node.getAttribute('glmr')) {
this.clearedNodes.push(node);
}
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
import { serializeBuilder } from '@glimmer/node';
import { ASTPluginBuilder } from '@glimmer/syntax';
import { createConstRef, Reference } from '@glimmer/reference';
import { cast } from '@glimmer/runtime';
import createHTMLDocument from '@simple-dom/document';
import {
SimpleDocument,
Expand Down Expand Up @@ -69,7 +70,7 @@ export class RehydrationDelegate implements RenderDelegate {
constructor(options?: RenderDelegateOptions) {
let delegate = assign(options?.env ?? {}, BaseEnv);

this.clientDoc = document as SimpleDocument;
this.clientDoc = cast(document).simple;
this.clientResolver = new TestJitRuntimeResolver();
this.clientRegistry = this.clientResolver.registry;
this.clientEnv = JitDelegateContext(
Expand Down Expand Up @@ -227,5 +228,5 @@ export class RehydrationDelegate implements RenderDelegate {
}

export function qunitFixture(): SimpleElement {
return document.getElementById('qunit-fixture') as SimpleElement;
return cast(document).getElementById('qunit-fixture');
}
3 changes: 2 additions & 1 deletion packages/@glimmer/integration-tests/lib/snapshot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { SimpleNode, NodeType, SimpleElement } from '@simple-dom/interface';
import { Option } from '@glimmer/interfaces';
import { replaceHTML, toInnerHTML } from './dom/simple-utils';
import { tokenize, EndTag, Token } from 'simple-html-tokenizer';
import { cast } from '@glimmer/runtime';

export type IndividualSnapshot = 'up' | 'down' | SimpleNode;
export type NodesSnapshot = IndividualSnapshot[];
Expand Down Expand Up @@ -86,7 +87,7 @@ export function generateSnapshot(element: SimpleElement): SimpleNode[] {
function generateTokens(divOrHTML: SimpleElement | string): { tokens: Token[]; html: string } {
let div: SimpleElement;
if (typeof divOrHTML === 'string') {
div = document.createElement('div') as SimpleElement;
div = cast(document).createElement('div');
replaceHTML(div, divOrHTML);
} else {
div = divOrHTML;
Expand Down
14 changes: 7 additions & 7 deletions packages/@glimmer/integration-tests/lib/suites/entry-point.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { DynamicScopeImpl } from '@glimmer/runtime';
import { DynamicScopeImpl, cast } from '@glimmer/runtime';
import { createPrimitiveRef } from '@glimmer/reference';
import { RenderTest, Count } from '../render-test';
import { ComponentKind } from '../components/types';
Expand All @@ -21,7 +21,7 @@ export class EntryPointTest extends RenderTest {
let title = createPrimitiveRef('renderComponent');
delegate.renderComponent('Title', { title }, element);

QUnit.assert.equal((element as Element).innerHTML, '<h1>hello renderComponent</h1>');
QUnit.assert.equal(cast(element, 'HTML').innerHTML, '<h1>hello renderComponent</h1>');
}

@test
Expand All @@ -32,12 +32,12 @@ export class EntryPointTest extends RenderTest {
let element = delegate.getInitialElement();
let title = createPrimitiveRef('renderComponent');
delegate.renderComponent('Title', { title }, element);
QUnit.assert.equal((element as Element).innerHTML, '<h1>hello renderComponent</h1>');
QUnit.assert.equal(cast(element, 'HTML').innerHTML, '<h1>hello renderComponent</h1>');

element = delegate.getInitialElement();
let newTitle = createPrimitiveRef('new title');
delegate.renderComponent('Title', { title: newTitle }, element);
QUnit.assert.equal((element as Element).innerHTML, '<h1>hello new title</h1>');
QUnit.assert.equal(cast(element, 'HTML').innerHTML, '<h1>hello new title</h1>');
}

@test
Expand All @@ -49,12 +49,12 @@ export class EntryPointTest extends RenderTest {
let element = delegate.getInitialElement();
let title = createPrimitiveRef('renderComponent');
delegate.renderComponent('Title', { title }, element);
QUnit.assert.equal((element as Element).innerHTML, '<h1>hello renderComponent</h1>');
QUnit.assert.equal(cast(element, 'HTML').innerHTML, '<h1>hello renderComponent</h1>');

element = delegate.getInitialElement();
let body = createPrimitiveRef('text');
delegate.renderComponent('Body', { body }, element);
QUnit.assert.equal((element as Element).innerHTML, '<p>body text</p>');
QUnit.assert.equal(cast(element, 'HTML').innerHTML, '<p>body text</p>');
}

@test
Expand All @@ -68,6 +68,6 @@ export class EntryPointTest extends RenderTest {
});
delegate.renderComponent('Locale', {}, element, dynamicScope);

QUnit.assert.equal((element as Element).innerHTML, 'en_US');
QUnit.assert.equal(cast(element, 'HTML').innerHTML, 'en_US');
}
}
Loading

0 comments on commit 88d0dbf

Please sign in to comment.