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

fix: correctly serialize Infinity as island props #12121

Merged
merged 1 commit into from
Oct 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/beige-rice-tap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'astro': patch
---

Support passing the values `Infinity` and `-Infinity` as island props.
8 changes: 7 additions & 1 deletion packages/astro/e2e/fixtures/pass-js/src/components/React.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ interface Props {
array: any[];
map: Map<string, string>;
set: Set<string>;
infinity: number;
negativeInfinity: number;
}

const isNode = typeof process !== 'undefined' && Object.prototype.toString.call(process) === '[object process]';

/** a counter written in React */
export default function Component({ undefined: undefinedProp, null: nullProp, boolean, number, string, bigint, object, array, map, set }: Props) {
export default function Component({ undefined: undefinedProp, null: nullProp, boolean, number, string, bigint, object, array, map, set, infinity, negativeInfinity }: Props) {
// We are testing hydration, so don't return anything in the server.
if(isNode) {
return <div></div>
Expand All @@ -30,6 +32,10 @@ export default function Component({ undefined: undefinedProp, null: nullProp, bo
<span id="boolean-value">{boolean.toString()}</span>
<span id="number-type">{Object.prototype.toString.call(number)}</span>
<span id="number-value">{number.toString()}</span>
<span id="infinity-type">{Object.prototype.toString.call(infinity)}</span>
<span id="infinity-value">{infinity.toString()}</span>
<span id="negative-infinity-type">{Object.prototype.toString.call(negativeInfinity)}</span>
<span id="negative-infinity-value">{negativeInfinity.toString()}</span>
<span id="string-type">{Object.prototype.toString.call(string)}</span>
<span id="string-value">{string}</span>
<span id="bigint-type">{Object.prototype.toString.call(bigint)}</span>
Expand Down
2 changes: 2 additions & 0 deletions packages/astro/e2e/fixtures/pass-js/src/pages/index.astro
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ set.add('test2');
array={[0, "foo"]}
map={map}
set={set}
infinity={Infinity}
negativeInfinity={-Infinity}
/>
</main>
</body>
Expand Down
16 changes: 16 additions & 0 deletions packages/astro/e2e/pass-js.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,22 @@ test.describe('Passing JS into client components', () => {
await expect(numberValue, 'is visible').toBeVisible();
await expect(numberValue).toHaveText('16');

const infinityType = page.locator('#infinity-type');
await expect(infinityType, 'is visible').toBeVisible();
await expect(infinityType).toHaveText('[object Number]');

const negativeInfinityType = page.locator('#negative-infinity-type');
await expect(negativeInfinityType, 'is visible').toBeVisible();
await expect(negativeInfinityType).toHaveText('[object Number]');

const infinityValue = page.locator('#infinity-value');
await expect(infinityValue, 'is visible').toBeVisible();
await expect(infinityValue).toHaveText('Infinity');

const negativeInfinityValue = page.locator('#negative-infinity-value');
await expect(negativeInfinityValue, 'is visible').toBeVisible();
await expect(negativeInfinityValue).toHaveText('-Infinity');

// string
const stringType = page.locator('#string-type');
await expect(stringType, 'is visible').toBeVisible();
Expand Down
1 change: 1 addition & 0 deletions packages/astro/src/runtime/server/astro-island.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ declare const Astro: {
8: (value) => new Uint8Array(value),
9: (value) => new Uint16Array(value),
10: (value) => new Uint32Array(value),
11: (value) => Infinity * value,
};

// Not using JSON.parse reviver because it's bottom-up but we want top-down
Expand Down
13 changes: 10 additions & 3 deletions packages/astro/src/runtime/server/serialize.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ const PROP_TYPE = {
Uint8Array: 8,
Uint16Array: 9,
Uint32Array: 10,
Infinity: 11,
};

function serializeArray(
Expand Down Expand Up @@ -93,11 +94,17 @@ function convertToSerializedForm(
default: {
if (value !== null && typeof value === 'object') {
return [PROP_TYPE.Value, serializeObject(value, metadata, parents)];
} else if (value === undefined) {
}
if (value === Infinity) {
return [PROP_TYPE.Infinity, 1];
}
if (value === -Infinity) {
return [PROP_TYPE.Infinity, -1];
}
if (value === undefined) {
return [PROP_TYPE.Value];
} else {
return [PROP_TYPE.Value, value];
}
return [PROP_TYPE.Value, value];
}
}
}
Expand Down
5 changes: 5 additions & 0 deletions packages/astro/test/serialize.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,11 @@ describe('serialize', () => {
const output = `{"a":[10,[1,2,3]]}`;
assert.equal(serializeProps(input), output);
});
it('serializes Infinity and -Infinity', () => {
const input = { a: Infinity, b: -Infinity };
const output = `{"a":[11,1],"b":[11,-1]}`;
assert.equal(serializeProps(input), output);
})
it('cannot serialize a cyclic reference', () => {
const a = {};
a.b = a;
Expand Down
Loading