Merge remote-tracking branch 'origin/main' into svelte-custom-renderer

svelte-custom-renderer
paoloricciuti 2 weeks ago
commit e20068fdbf

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: omit `bind:focused` from SSR output (it has no HTML attribute)

@ -0,0 +1,5 @@
---
'svelte': patch
---
fix: properly apply static textarea value attribute during CSR

@ -0,0 +1,5 @@
---
'svelte': minor
---
feat: add `has` function to `createContext`

@ -0,0 +1,5 @@
---
'svelte': minor
---
feat: add getOrInsert/getOrInsertComputed to SvelteMap

@ -4,7 +4,7 @@ title: Context
Context allows components to access values owned by parent components without passing them down as props (potentially through many layers of intermediate components, known as 'prop-drilling').
By creating a `[get, set]` pair of functions with `createContext`, you can set the context in a parent component and get it in a child component:
By creating a `[get, set, has]` triplet of functions with `createContext`, you can set the context in a parent component and get it in a child component:
<!-- codeblock:start {"title":"Context","selected":"context.ts"} -->
```svelte

@ -78,7 +78,7 @@ Certain lifecycle methods can only be used during component initialisation. To f
Context was not set in the current component or any of its ancestors
```
The [`createContext()`](svelte#createContext) utility returns a `[get, set]` pair of functions. `get` will throw an error if `set` was not used to set the context in the current component or any of its ancestors.
The [`createContext()`](svelte#createContext) utility returns a `[get, set, has]` triplet of functions. `get` will throw an error if `set` was not used to set the context in the current component or any of its ancestors.
### snippet_without_render_tag

@ -37,7 +37,7 @@
"eslint-plugin-lube": "^0.5.1",
"eslint-plugin-svelte": "^3.15.0",
"jsdom": "25.0.1",
"playwright": "^1.60.0",
"playwright": "^1.62.0",
"prettier": "^3.2.4",
"prettier-plugin-svelte": "^3.4.0",
"svelte": "workspace:^",

@ -64,7 +64,7 @@ Certain lifecycle methods can only be used during component initialisation. To f
> Context was not set in the current component or any of its ancestors
The [`createContext()`](svelte#createContext) utility returns a `[get, set]` pair of functions. `get` will throw an error if `set` was not used to set the context in the current component or any of its ancestors.
The [`createContext()`](svelte#createContext) utility returns a `[get, set, has]` triplet of functions. `get` will throw an error if `set` was not used to set the context in the current component or any of its ancestors.
## snippet_without_render_tag

@ -159,7 +159,7 @@
},
"devDependencies": {
"@jridgewell/trace-mapping": "^0.3.25",
"@playwright/test": "^1.60.0",
"@playwright/test": "^1.62.0",
"@rollup/plugin-commonjs": "^28.0.1",
"@rollup/plugin-node-resolve": "^15.3.0",
"@rollup/plugin-terser": "^0.4.4",

@ -247,6 +247,7 @@ export function RegularElement(node, context) {
if (
!is_custom_element &&
!cannot_be_set_statically(attribute.name) &&
(name !== 'value' || node.name !== 'textarea') &&
(attribute.value === true || is_text_attribute(attribute)) &&
(name !== 'class' || class_directives.length === 0) &&
(name !== 'style' || style_directives.length === 0)

@ -23,7 +23,9 @@ export const binding_properties = {
event: 'durationchange',
omit_in_ssr: true
},
focused: {},
focused: {
omit_in_ssr: true // no corresponding HTML attribute
},
paused: {
valid_elements: ['audio', 'video'],
omit_in_ssr: true,

@ -72,17 +72,17 @@ export function set_dev_current_component_function(fn) {
}
/**
* Returns a `[get, set]` pair of functions for working with context in a type-safe way.
* Returns a `[get, set, has]` triplet of functions for working with context in a type-safe way.
*
* `get` will throw an error if `set` has not yet been called in the current component or any of
* its ancestors.
*
* @template T
* @returns {[() => T, (context: T) => T]}
* @returns {[() => T, (context: T) => T, () => boolean]}
* @since 5.40.0
*/
export function createContext() {
return /** @type {[() => T, (context: T) => T]} */ (
return /** @type {[() => T, (context: T) => T, () => boolean]} */ (
create_context(getContext, setContext, hasContext)
);
}

@ -12,11 +12,11 @@ export function set_ssr_context(v) {
/**
* @template T
* @returns {[() => T, (context: T) => T]}
* @returns {[() => T, (context: T) => T, () => boolean]}
* @since 5.40.0
*/
export function createContext() {
return /** @type {[() => T, (context: T) => T]} */ (
return /** @type {[() => T, (context: T) => T, () => boolean]} */ (
create_context(getContext, setContext, hasContext)
);
}

@ -5,7 +5,7 @@ import { lifecycle_outside_component, missing_context } from './errors.js';
* @param {(key: object) => T} get_context
* @param {(key: object, context: T) => T} set_context
* @param {(key: object) => boolean} has_context
* @returns {[() => T, (context: T) => T]}
* @returns {[() => T, (context: T) => T, () => boolean]}
*/
export function create_context(get_context, set_context, has_context) {
const key = {};
@ -18,7 +18,8 @@ export function create_context(get_context, set_context, has_context) {
return get_context(key);
},
(context) => set_context(key, context)
(context) => set_context(key, context),
() => has_context(key)
];
}

@ -153,6 +153,28 @@ export class SvelteMap extends Map {
return super.get(key);
}
/**
* @param {K} key
* @param {V} value
* */
getOrInsert(key, value) {
if (!super.has(key)) {
this.set(key, value);
}
return /** @type {V} */ (this.get(key));
}
/**
* @param {K} key
* @param {(key: K) => V} callbackFn
*/
getOrInsertComputed(key, callbackFn) {
if (!super.has(key)) {
this.set(key, callbackFn(key));
}
return /** @type {V} */ (this.get(key));
}
/**
* @param {K} key
* @param {V} value

@ -100,6 +100,85 @@ test('map.get(...)', () => {
cleanup();
});
test('map.getOrInsert(...)', () => {
const map = new SvelteMap([
[2, 2],
[3, 3]
]);
const log: any = [];
const cleanup = effect_root(() => {
render_effect(() => {
log.push('get 1', map.getOrInsert(1, 1));
});
render_effect(() => {
log.push('get 2', map.getOrInsert(2, 2));
});
render_effect(() => {
log.push('get 3', map.getOrInsert(3, 4));
});
});
flushSync(() => {
map.delete(2);
});
flushSync(() => {
map.set(2, 2);
});
assert.deepEqual(log, ['get 1', 1, 'get 2', 2, 'get 3', 3, 'get 2', 2]);
cleanup();
});
test('map.getOrInsertComputed(...)', () => {
const map = new SvelteMap([
[2, 2],
[3, 3]
]);
const log: any = [];
const cleanup = effect_root(() => {
render_effect(() => {
log.push(
'get 1',
map.getOrInsertComputed(1, (k) => k)
);
});
render_effect(() => {
log.push(
'get 2',
map.getOrInsertComputed(2, (k) => k)
);
});
render_effect(() => {
log.push(
'get 3',
map.getOrInsertComputed(3, () => 4)
);
});
});
flushSync(() => {
map.delete(2);
});
flushSync(() => {
map.set(2, 2);
});
assert.deepEqual(log, ['get 1', 1, 'get 2', 2, 'get 3', 3, 'get 2', 2]);
cleanup();
});
test('map.has(...)', () => {
const map = new SvelteMap([
[1, 1],

@ -5,14 +5,19 @@ export default test({
return { foo: 42 };
},
html: '<textarea></textarea>',
ssrHtml: '<textarea>42</textarea>',
ssrHtml: '<textarea>42</textarea> <textarea>static</textarea>',
test({ assert, component, target }) {
const textarea = /** @type {HTMLTextAreaElement} */ (target.querySelector('textarea'));
assert.strictEqual(textarea.value, '42');
test({ assert, component, target, variant }) {
assert.htmlEqual(
target.innerHTML,
`<textarea></textarea> <textarea>${variant === 'hydrate' ? 'static' : ''}</textarea>`
);
const [textarea1, textarea2] = target.querySelectorAll('textarea');
assert.strictEqual(textarea1.value, '42');
assert.strictEqual(textarea2.value, 'static');
component.foo = 43;
assert.strictEqual(textarea.value, '43');
assert.strictEqual(textarea1.value, '43');
}
});

@ -3,3 +3,4 @@
</script>
<textarea value='{foo}'/>
<textarea value="static"></textarea>

@ -1,7 +1,13 @@
<script>
import { get } from './main.svelte';
import { get, has, has_unset } from './main.svelte';
const message = get();
</script>
<h1>{message}</h1>
{#if has()}
<h2>it's me</h2>
{/if}
{#if !has_unset()}
<h2>or not</h2>
{/if}

@ -2,7 +2,7 @@ import { test } from '../../test';
export default test({
ssrHtml: `<div></div>`,
html: `<div><h1>hello</h1></div>`,
html: `<div><h1>hello</h1><h2>it's me</h2><h2>or not</h2></div>`,
test() {}
});

@ -3,9 +3,11 @@
import Child from './Child.svelte';
/** @type {ReturnType<typeof createContext<string>>} */
const [get, set] = createContext();
const [get, set, has] = createContext();
/** @type {ReturnType<typeof createContext<string>>} */
const [, , has_unset] = createContext();
export { get };
export { get, has, has_unset };
function Wrapper(Component) {
return (...args) => {
@ -15,6 +17,8 @@
}
</script>
<div {@attach (target) => {
<div
{@attach (target) => {
mount(Wrapper(Child), { target });
}}></div>
}}
></div>

@ -1,7 +1,13 @@
<script>
import { get } from './main.svelte';
import { get, has, has_unset } from './main.svelte';
const message = get();
</script>
<h1>{message}</h1>
{#if has()}
<h2>it's me</h2>
{/if}
{#if !has_unset()}
<h2>or not</h2>
{/if}

@ -1,5 +1,5 @@
import { test } from '../../test';
export default test({
html: `<h1>hello</h1>`
html: `<h1>hello</h1><h2>it's me</h2><h2>or not</h2>`
});

@ -2,9 +2,11 @@
import { createContext } from 'svelte';
/** @type {ReturnType<typeof createContext<string>>} */
const [get, set] = createContext();
const [get, set, has] = createContext();
/** @type {ReturnType<typeof createContext<string>>} */
const [, , has_unset] = createContext();
export { get };
export { get, has, has_unset };
</script>
<script>

@ -529,14 +529,14 @@ declare module 'svelte' {
*/
export function fork(fn: () => void): Fork;
/**
* Returns a `[get, set]` pair of functions for working with context in a type-safe way.
* Returns a `[get, set, has]` triplet of functions for working with context in a type-safe way.
*
* `get` will throw an error if `set` has not yet been called in the current component or any of
* its ancestors.
*
* @since 5.40.0
*/
export function createContext<T>(): [() => T, (context: T) => T];
export function createContext<T>(): [() => T, (context: T) => T, () => boolean];
/**
* Retrieves the context set with the specified `key` in the current component or any of its
* ancestors. If multiple components set the same key, the value from the closest one is returned.
@ -2517,6 +2517,10 @@ declare module 'svelte/reactivity' {
constructor(value?: Iterable<readonly [K, V]> | null | undefined);
getOrInsert(key: K, value: V): V;
getOrInsertComputed(key: K, callbackFn: (key: K) => V): V;
set(key: K, value: V): this;
#private;
}

@ -42,8 +42,8 @@ importers:
specifier: 25.0.1
version: 25.0.1
playwright:
specifier: ^1.60.0
version: 1.60.0
specifier: ^1.62.0
version: 1.62.1
prettier:
specifier: ^3.2.4
version: 3.2.4
@ -121,8 +121,8 @@ importers:
specifier: ^0.3.25
version: 0.3.31
'@playwright/test':
specifier: ^1.60.0
version: 1.60.0
specifier: ^1.62.0
version: 1.62.1
'@rollup/plugin-commonjs':
specifier: ^28.0.1
version: 28.0.1(rollup@4.60.1)
@ -723,9 +723,9 @@ packages:
resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
engines: {node: '>= 8'}
'@playwright/test@1.60.0':
resolution: {integrity: sha512-O71yZIbAh/PxDMNGns37GHBIfrVkEVyn+AXyIa5dOTfb4/xNvRWV+Vv/NMbNCtODB/pO7vLlF2OTmMVLhmr7Ag==}
engines: {node: '>=18'}
'@playwright/test@1.62.1':
resolution: {integrity: sha512-DTcUc8qii+cpHvtOwggMtBRMjKZHXYWdw8syRYu2vtzuq4Wxphqq4NfCs5Zt44L6mA8rfDfj+PHnxFc/FeK6mQ==}
engines: {node: '>=20'}
hasBin: true
'@polka/url@1.0.0-next.25':
@ -840,131 +840,157 @@ packages:
resolution: {integrity: sha512-L+34Qqil+v5uC0zEubW7uByo78WOCIrBvci69E7sFASRl0X7b/MB6Cqd1lky/CtcSVTydWa2WZwFuWexjS5o6g==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm-gnueabihf@4.62.2':
resolution: {integrity: sha512-n1GJHPOvpIfhi3TmrCeh6S6URt9BFCt0KQE3qvexyGCTAKpR4Lg+eWvNZEqu7epxwus/8ElT3hacYEucm49SZg==}
cpu: [arm]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm-musleabihf@4.60.1':
resolution: {integrity: sha512-n83O8rt4v34hgFzlkb1ycniJh7IR5RCIqt6mz1VRJD6pmhRi0CXdmfnLu9dIUS6buzh60IvACM842Ffb3xd6Gg==}
cpu: [arm]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-arm-musleabihf@4.62.2':
resolution: {integrity: sha512-JqgflS8wEB+UXV/vS1RpRbifGBeN4D5lz8D8oOFbFZw4vedvdOgCFAjfBmIMdW3yL10XpQQ0Ambepw6MXrhOnA==}
cpu: [arm]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-arm64-gnu@4.60.1':
resolution: {integrity: sha512-Nql7sTeAzhTAja3QXeAI48+/+GjBJ+QmAH13snn0AJSNL50JsDqotyudHyMbO2RbJkskbMbFJfIJKWA6R1LCJQ==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm64-gnu@4.62.2':
resolution: {integrity: sha512-wnFJkogWvN4jm/hQRF2UBaeUmk20j5+DmHvoyWii2b8HJDyvz1MF2OU/6ynXt2KR63rbZLWkFpoytpdc/yBuSA==}
cpu: [arm64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-arm64-musl@4.60.1':
resolution: {integrity: sha512-+pUymDhd0ys9GcKZPPWlFiZ67sTWV5UU6zOJat02M1+PiuSGDziyRuI/pPue3hoUwm2uGfxdL+trT6Z9rxnlMA==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-arm64-musl@4.62.2':
resolution: {integrity: sha512-HVu2bp0zhvJ8xHEV9+UUs7S90VadmBSY3LcIMvozbPo4AuMGDWlz3ymHLHZPX4hR67TKTt8Qp5PJ5RBg/i+RMQ==}
cpu: [arm64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-loong64-gnu@4.60.1':
resolution: {integrity: sha512-VSvgvQeIcsEvY4bKDHEDWcpW4Yw7BtlKG1GUT4FzBUlEKQK0rWHYBqQt6Fm2taXS+1bXvJT6kICu5ZwqKCnvlQ==}
cpu: [loong64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-loong64-gnu@4.62.2':
resolution: {integrity: sha512-mQqqAV8QaoSgr9I2fKDLY2BAVvmKjWoGiu/cSYQonsLvtqwEn1E4QYfnCOcp5zoEqNhsDYin1s6jx/VJmrxlZg==}
cpu: [loong64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-loong64-musl@4.60.1':
resolution: {integrity: sha512-4LqhUomJqwe641gsPp6xLfhqWMbQV04KtPp7/dIp0nzPxAkNY1AbwL5W0MQpcalLYk07vaW9Kp1PBhdpZYYcEw==}
cpu: [loong64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-loong64-musl@4.62.2':
resolution: {integrity: sha512-IxKLoxCQ2IWi6bT2akyDUBGsOImDKB+sPp4EsTmwFQ/fMwpCKm8uLSSgP/Kx/QYUgKis6SEZ5/Nlhup0DIA0PQ==}
cpu: [loong64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-ppc64-gnu@4.60.1':
resolution: {integrity: sha512-tLQQ9aPvkBxOc/EUT6j3pyeMD6Hb8QF2BTBnCQWP/uu1lhc9AIrIjKnLYMEroIz/JvtGYgI9dF3AxHZNaEH0rw==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-ppc64-gnu@4.62.2':
resolution: {integrity: sha512-Mk5ha2RQSgyFfmYYLkBpPnUk8D8FriBxesO1u9O75X0mHgXL1UQcH5Itl2lurWL2tj0RxV9b9tJgipac0hRY9A==}
cpu: [ppc64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-ppc64-musl@4.60.1':
resolution: {integrity: sha512-RMxFhJwc9fSXP6PqmAz4cbv3kAyvD1etJFjTx4ONqFP9DkTkXsAMU4v3Vyc5BgzC+anz7nS/9tp4obsKfqkDHg==}
cpu: [ppc64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-ppc64-musl@4.62.2':
resolution: {integrity: sha512-CjvEnqJL/0/TQ3TXX3OPIJ/kmBellrWd4heXUmHeJlTnmwjKpSJzoehLaL6Xk0ZnMHBu9dZuFADNOrtjF4v+2w==}
cpu: [ppc64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-riscv64-gnu@4.60.1':
resolution: {integrity: sha512-QKgFl+Yc1eEk6MmOBfRHYF6lTxiiiV3/z/BRrbSiW2I7AFTXoBFvdMEyglohPj//2mZS4hDOqeB0H1ACh3sBbg==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-riscv64-gnu@4.62.2':
resolution: {integrity: sha512-1SiZbzwdkaDURsew/tSOrooKiYy7EQGT6m8ufavAi9NEyQb/6VuIxFXAL1fqa4iZe3g4NbNk4P7J32z2tw5Mgg==}
cpu: [riscv64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-riscv64-musl@4.60.1':
resolution: {integrity: sha512-RAjXjP/8c6ZtzatZcA1RaQr6O1TRhzC+adn8YZDnChliZHviqIjmvFwHcxi4JKPSDAt6Uhf/7vqcBzQJy0PDJg==}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-riscv64-musl@4.62.2':
resolution: {integrity: sha512-nQts12zJ3NQRoE6uYljOH89v7szzLDvG2JD/vsX+vGXU8w/At1GowTZ5/7qeFQ8m7L55rpR8Okugnuo5bgjy2Q==}
cpu: [riscv64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-s390x-gnu@4.60.1':
resolution: {integrity: sha512-wcuocpaOlaL1COBYiA89O6yfjlp3RwKDeTIA0hM7OpmhR1Bjo9j31G1uQVpDlTvwxGn2nQs65fBFL5UFd76FcQ==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-s390x-gnu@4.62.2':
resolution: {integrity: sha512-E9/ll019jhPIJgpzfZoIkBGhcz+kKNgVWYRY0zr9srBdPPFVpvOKW8VaJKUbeK+eZXyQF9ltME+Kk6affeaPgg==}
cpu: [s390x]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.60.1':
resolution: {integrity: sha512-77PpsFQUCOiZR9+LQEFg9GClyfkNXj1MP6wRnzYs0EeWbPcHs02AXu4xuUbM1zhwn3wqaizle3AEYg5aeoohhg==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-gnu@4.62.2':
resolution: {integrity: sha512-5BqxR/pshjey51iliyzTD5Xi3EN0aLmQ2lZ3lvefVV9c82BvrLo2/6OT55iifpWBufs6kdwWbuOKS841DrmK9A==}
cpu: [x64]
os: [linux]
libc: [glibc]
'@rollup/rollup-linux-x64-musl@4.60.1':
resolution: {integrity: sha512-5cIATbk5vynAjqqmyBjlciMJl1+R/CwX9oLk/EyiFXDWd95KpHdrOJT//rnUl4cUcskrd0jCCw3wpZnhIHdD9w==}
cpu: [x64]
os: [linux]
libc: [musl]
'@rollup/rollup-linux-x64-musl@4.62.2':
resolution: {integrity: sha512-uNN83XxQrRAh/w0/pmAfibcwyb6YWt4gP+dpnQKPVJshAloQ785ii8CT8ZCIxkGg9opVsvAlGhFitSm6D1Jjpg==}
cpu: [x64]
os: [linux]
libc: [musl]
'@rollup/rollup-openbsd-x64@4.60.1':
resolution: {integrity: sha512-cl0w09WsCi17mcmWqqglez9Gk8isgeWvoUZ3WiJFYSR3zjBQc2J5/ihSjpl+VLjPqjQ/1hJRcqBfLjssREQILw==}
@ -1875,24 +1901,28 @@ packages:
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [glibc]
lightningcss-linux-arm64-musl@1.23.0:
resolution: {integrity: sha512-cU00LGb6GUXCwof6ACgSMKo3q7XYbsyTj0WsKHLi1nw7pV0NCq8nFTn6ZRBYLoKiV8t+jWl0Hv8KkgymmK5L5g==}
engines: {node: '>= 12.0.0'}
cpu: [arm64]
os: [linux]
libc: [musl]
lightningcss-linux-x64-gnu@1.23.0:
resolution: {integrity: sha512-q4jdx5+5NfB0/qMbXbOmuC6oo7caPnFghJbIAV90cXZqgV8Am3miZhC4p+sQVdacqxfd+3nrle4C8icR3p1AYw==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [glibc]
lightningcss-linux-x64-musl@1.23.0:
resolution: {integrity: sha512-G9Ri3qpmF4qef2CV/80dADHKXRAQeQXpQTLx7AiQrBYQHqBjB75oxqj06FCIe5g4hNCqLPnM9fsO4CyiT1sFSQ==}
engines: {node: '>= 12.0.0'}
cpu: [x64]
os: [linux]
libc: [musl]
lightningcss-win32-x64-msvc@1.23.0:
resolution: {integrity: sha512-1rcBDJLU+obPPJM6qR5fgBUiCdZwZLafZM5f9kwjFLkb/UBNIzmae39uCSmh71nzPCTXZqHbvwu23OWnWEz+eg==}
@ -2077,14 +2107,14 @@ packages:
resolution: {integrity: sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==}
engines: {node: '>=6'}
playwright-core@1.60.0:
resolution: {integrity: sha512-9bW6zvX/m0lEbgTKJ6YppOKx8H3VOPBMOCFh2irXFOT4BbHgrx5hPjwJYLT40Lu+4qtD36qKc/Hn56StUW57IA==}
engines: {node: '>=18'}
playwright-core@1.62.1:
resolution: {integrity: sha512-wPYSwEBJY9GHraISXqyqtx0na0LpO3XEX7jNDhntbex7tzUS7kLnZsOlFruFJB4Hi/rhDMjXGqHewDZ68nYZVw==}
engines: {node: '>=20'}
hasBin: true
playwright@1.60.0:
resolution: {integrity: sha512-hheHdokM8cdqCb0lcE3s+zT4t4W+vvjpGxsZlDnikarzx8tSzMebh3UiFtgqwFwnTnjYQcsyMF8ei2mCO/tpeA==}
engines: {node: '>=18'}
playwright@1.62.1:
resolution: {integrity: sha512-0M+L3LAD8/nm554LOla9Ayx0j0tmFZ0FBcoQ7F1VuVHpM/XpiC8RcDzBQB8W5+hA8L22THxELzeF+2WcUzvcLg==}
engines: {node: '>=20'}
hasBin: true
polka@1.0.0-next.25:
@ -3069,9 +3099,9 @@ snapshots:
'@nodelib/fs.scandir': 2.1.5
fastq: 1.16.0
'@playwright/test@1.60.0':
'@playwright/test@1.62.1':
dependencies:
playwright: 1.60.0
playwright: 1.62.1
'@polka/url@1.0.0-next.25': {}
@ -4371,11 +4401,11 @@ snapshots:
pify@4.0.1: {}
playwright-core@1.60.0: {}
playwright-core@1.62.1: {}
playwright@1.60.0:
playwright@1.62.1:
dependencies:
playwright-core: 1.60.0
playwright-core: 1.62.1
optionalDependencies:
fsevents: 2.3.2

Loading…
Cancel
Save