Repository navigation
perf(core): the keyboard notifications' duration has its own export #8484
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
3f83540
6c61c92
216d05c
9865edf
1adf75c
218ca70
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| --- | ||
| '@astryxdesign/core': patch | ||
| --- | ||
|
|
||
| [chore] Internal: the keyboard notifications' duration has its own export in the UIKit timing table, so code that reads only it bundles no other timing value. Not exported from the package entry point. | ||
|
|
||
| @vjeux |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| // Copyright (c) Meta Platforms, Inc. and affiliates. | ||
|
|
||
| /** | ||
| * @file keyboardNotification.test.ts | ||
| * @input timing.ts, bundled on its own with esbuild | ||
| * @output Proof that the keyboard notifications' duration is its own export: | ||
| * the timing table composes it, and a bundle that reads only it carries no | ||
| * other row of the table | ||
| * @position Guards architecture:component-style-authoring INV6 for the | ||
| * keyboard layout guide's one read of the timing table | ||
| */ | ||
|
|
||
| import {execFileSync} from 'node:child_process'; | ||
| import {describe, expect, it} from 'vitest'; | ||
| import {keyboardNotification, timing} from './timing'; | ||
|
|
||
| describe('keyboardNotification', () => { | ||
| it('is the timing table\u2019s keyboard duration', () => { | ||
| expect(timing.keyboardNotificationMs).toBe(keyboardNotification.durationMs); | ||
| }); | ||
|
|
||
| it('a bundle that reads only the keyboard\u2019s duration drops the rest of the table', () => { | ||
| // esbuild runs in its own Node process: jsdom's TextEncoder fails its | ||
| // startup check. | ||
| const code = execFileSync( | ||
| process.execPath, | ||
| [ | ||
| '--input-type=module', | ||
| '-e', | ||
| [ | ||
| "import {build} from 'esbuild';", | ||
| 'const result = await build({', | ||
| " stdin: {contents: \"import {keyboardNotification} from './timing'; export const ms = keyboardNotification.durationMs;\", resolveDir: process.cwd(), loader: 'ts'},", | ||
| " bundle: true, write: false, format: 'esm', minify: true, logLevel: 'silent',", | ||
| '});', | ||
| 'process.stdout.write(result.outputFiles[0].text);', | ||
| ].join('\n'), | ||
| ], | ||
| {cwd: __dirname, encoding: 'utf8'}, | ||
| ); | ||
| expect(code).toContain('383.3'); | ||
| // No other row: not the navigation bar's duration, not the press clocks. | ||
| expect(code).not.toContain('navigationBarHideShowMs'); | ||
| expect(code).not.toContain('buttonReleaseMs'); | ||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -83,6 +83,28 @@ export const press = { | |
| buttonReleaseMs: 250, | ||
| } as const; | ||
|
|
||
| /** | ||
| * The keyboard notifications' duration, its own export so the keyboard layout | ||
| * guide reads it without the rest of the table | ||
| * (`architecture:component-style-authoring` INV6). `timing` composes it under | ||
| * its table path, `keyboardNotificationMs`, which stays out of the roles. | ||
| */ | ||
| export const keyboardNotification = { | ||
| /** | ||
| * The duration the keyboard notifications report | ||
| * (UIKeyboardAnimationDurationUserInfoKey, with curve 7), show and hide | ||
| * alike, in ms. The frame follows `springs.keyboard`, cut at this time. | ||
| * @source measured: UIKit lab (injected host app), iOS 26.2 simulator, | ||
| * iPhone 17 Pro, UIKeyboardWillShow / WillHide / WillChangeFrame read, | ||
| * Oct 23 2026 | ||
| */ | ||
| durationMs: 383.3, | ||
| } as const; | ||
|
|
||
| // Composed from a binding, so a bundle that reads only the keyboard's | ||
| // duration drops the rest of the table. | ||
| const {durationMs: keyboardNotificationMs} = keyboardNotification; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. esbuild keeps this top-level destructuring in every bundle that includes
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Fixed in 9865edf: each value is now one sourced constant ( |
||
|
|
||
| /** | ||
| * The Reduce Motion fade, its own export so the animator reads it without | ||
| * the rest of the table (`architecture:component-style-authoring` INV6). | ||
|
|
@@ -161,15 +183,7 @@ export const timing = { | |
| * iPhone 17 Pro, read, Oct 23 2026 | ||
| */ | ||
| navigationBarHideShowMs: 200, | ||
| /** | ||
| * The duration the keyboard notifications report | ||
| * (UIKeyboardAnimationDurationUserInfoKey, with curve 7), show and hide | ||
| * alike, in ms. The frame follows `springs.keyboard`, cut at this time. | ||
| * @source measured: UIKit lab (injected host app), iOS 26.2 simulator, | ||
| * iPhone 17 Pro, UIKeyboardWillShow / WillHide / WillChangeFrame read, | ||
| * Oct 23 2026 | ||
| */ | ||
| keyboardNotificationMs: 383.3, | ||
| keyboardNotificationMs, | ||
| /** | ||
| * Core Animation's implicit animation duration | ||
| * (`CATransaction.animationDuration()`), in ms. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
At this head this build is
var e={durationMs:383.3},{durationMs:s}=e,o={durationMs:500,curve:[.42,0,.58,1]},…: it carries the Reduce Motion fade row through the binding attiming.ts:144-145, which these two assertions don't name, so the test passes while the bundle still carries another row. Asserting, for example,expect(code).not.toContain('durationMs:500')makes it fail today.