Skip to content
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

feat: Typing improvements to preload PR #7841

Merged
merged 12 commits into from
Nov 28, 2022
6 changes: 3 additions & 3 deletions packages/kit/src/runtime/client/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { HttpError, Redirect } from '../control.js';
import { stores } from './singletons.js';
import { unwrap_promises } from '../../utils/promises.js';
import * as devalue from 'devalue';
import { INDEX_KEY, PRIORITY_PAGE, PRIORITY_VIEWPORT, SCROLL_KEY } from './constants.js';
import { INDEX_KEY, PRELOAD_PRIORITIES, SCROLL_KEY } from './constants.js';

const routes = parse(nodes, server_loads, dictionary, matchers);

Expand Down Expand Up @@ -1236,11 +1236,11 @@ export function create_client({ target, base }) {

if (external) continue;

if (options.preload_code === PRIORITY_VIEWPORT) {
if (options.preload_code === PRELOAD_PRIORITIES['viewport']) {
observer.observe(a);
}

if (options.preload_code === PRIORITY_PAGE) {
if (options.preload_code === PRELOAD_PRIORITIES['page']) {
preload_code(/** @type {URL} */ (url).pathname);
}
}
Expand Down
11 changes: 7 additions & 4 deletions packages/kit/src/runtime/client/constants.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
export const SCROLL_KEY = 'sveltekit:scroll';
export const INDEX_KEY = 'sveltekit:index';

export const PRIORITY_TAP = 1;
export const PRIORITY_HOVER = 2;
export const PRIORITY_VIEWPORT = 3;
export const PRIORITY_PAGE = 4;
export const PRELOAD_PRIORITIES = /** @type {const} */ ({
tap: 1,
hover: 2,
viewport: 3,
page: 4,
off: -1
});
103 changes: 59 additions & 44 deletions packages/kit/src/runtime/client/utils.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { writable } from 'svelte/store';
import { assets } from '../paths.js';
import { version } from '../env.js';
import { PRIORITY_HOVER, PRIORITY_PAGE, PRIORITY_TAP, PRIORITY_VIEWPORT } from './constants.js';
import { PRELOAD_PRIORITIES } from './constants.js';

/* global __SVELTEKIT_APP_VERSION_FILE__, __SVELTEKIT_APP_VERSION_POLL_INTERVAL__ */

Expand All @@ -26,34 +26,62 @@ export function scroll_state() {

const warned = new WeakSet();

/** @typedef { 'preload-code' | 'preload-data' | 'noscroll' | 'reload' } AnchorShortAttribute */
/** @typedef { `data-sveltekit-${AnchorShortAttribute}`} AnchorAttribute */

const anchor_attribute_valid_values = /** @type {const} */ ({
'data-sveltekit-preload-code': ['', 'off', 'tap', 'hover', 'viewport', 'page'],
'data-sveltekit-preload-data': ['', 'off', 'tap', 'hover'],
'data-sveltekit-noscroll': ['', 'off'],
'data-sveltekit-reload': ['', 'off']
});

/** @typedef {typeof anchor_attribute_valid_values['data-sveltekit-preload-data'][number]} PreloadDataValidValues */
/** @typedef {typeof anchor_attribute_valid_values['data-sveltekit-preload-code'][number]} PreloadCodeValidValues */
/** @typedef {typeof anchor_attribute_valid_values['data-sveltekit-noscroll'][number]} NoscrollValidValues */
/** @typedef {typeof anchor_attribute_valid_values['data-sveltekit-reload'][number]} ReloadValidValues */

/**
* @param {Element} element
* @param {string} name
* @param {T} attributeName
* @returns {typeof anchor_attribute_valid_values[T][number] | null}
* @template {AnchorAttribute} T
*/
function getValidatedAttribute(element, attributeName) {
const value = element.getAttribute(attributeName);
return validateAttributeValue(element, attributeName, value);
Rich-Harris marked this conversation as resolved.
Show resolved Hide resolved
}

/**
* @param {Element} element
* @param {T} attributeName
* @param {string | null} value
* @param {string[]} options
* @returns {typeof anchor_attribute_valid_values[T][number] | null}
* @template {AnchorAttribute} T
*/
function validate(element, name, value, options) {
if (warned.has(element)) return;
if (value === null) return;
if (!options.includes(value)) {
warned.add(element);
console.error(
`Unexpected value for ${name} — should be one of ${options
.map((option) => JSON.stringify(option))
.join(', ')}`,
element
);
function validateAttributeValue(element, attributeName, value) {
// we don't want to waste resources on validation in production
if (__SVELTEKIT_DEV__) {
if (warned.has(element) || value === null) return null;
// @ts-expect-error - includes is dumb
if (!anchor_attribute_valid_values[attributeName].includes(value)) {
console.error(
`Unexpected value for ${attributeName} — should be one of ${anchor_attribute_valid_values[
attributeName
]
.map((option) => JSON.stringify(option))
.join(', ')}`,
element
);
}
}

return /** @type {typeof anchor_attribute_valid_values[T][number] | null} */ (value);
}

/** @type {Record<string, number>} */
const levels = {
tap: PRIORITY_TAP,
hover: PRIORITY_HOVER,
viewport: PRIORITY_VIEWPORT,
page: PRIORITY_PAGE,
'': PRIORITY_HOVER,
off: -1
...PRELOAD_PRIORITIES,
'': PRELOAD_PRIORITIES['hover']
Rich-Harris marked this conversation as resolved.
Show resolved Hide resolved
};

/**
Expand All @@ -64,16 +92,16 @@ export function find_anchor(element, base) {
/** @type {HTMLAnchorElement | SVGAElement | undefined} */
let a;

/** @type {string | null} */
/** @type {NoscrollValidValues | null} */
let noscroll = null;

/** @type {string | null} */
/** @type {PreloadCodeValidValues | null} */
let preload_code = null;

/** @type {string | null} */
/** @type {PreloadDataValidValues | null} */
let preload_data = null;

/** @type {string | null} */
/** @type {ReloadValidValues | null} */
let reload = null;

while (element !== document.documentElement) {
Expand All @@ -83,25 +111,12 @@ export function find_anchor(element, base) {
}

if (a) {
if (preload_code === null) preload_code = element.getAttribute('data-sveltekit-preload-code');
if (preload_data === null) preload_data = element.getAttribute('data-sveltekit-preload-data');
if (noscroll === null) noscroll = element.getAttribute('data-sveltekit-noscroll');
if (reload === null) reload = element.getAttribute('data-sveltekit-reload');

if (__SVELTEKIT_DEV__) {
validate(element, 'data-sveltekit-preload-data', preload_data, ['', 'off', 'tap', 'hover']);
validate(element, 'data-sveltekit-preload-code', preload_code, [
'',
'off',
'tap',
'hover',
'viewport',
'page'
]);

validate(element, 'data-sveltekit-preload-data', noscroll, ['', 'off']);
validate(element, 'data-sveltekit-preload-data', reload, ['', 'off']);
}
if (preload_code === null)
preload_code = getValidatedAttribute(element, 'data-sveltekit-preload-code');
if (preload_data === null)
preload_data = getValidatedAttribute(element, 'data-sveltekit-preload-data');
if (noscroll === null) noscroll = getValidatedAttribute(element, 'data-sveltekit-noscroll');
if (reload === null) reload = getValidatedAttribute(element, 'data-sveltekit-reload');
}

// @ts-expect-error handle shadow roots
Expand Down
16 changes: 0 additions & 16 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.