mirror of
				https://github.com/microsoft/playwright.git
				synced 2025-06-26 21:40:17 +00:00 
			
		
		
		
	feat(evaluate): serialize map and set (#26730)
closes: https://github.com/microsoft/playwright/issues/24040
This commit is contained in:
		
							parent
							
								
									501ed32856
								
							
						
					
					
						commit
						ee203b782c
					
				@ -75,6 +75,10 @@ function innerParseSerializedValue(value: SerializedValue, handles: any[] | unde
 | 
			
		||||
    return BigInt(value.bi);
 | 
			
		||||
  if (value.r !== undefined)
 | 
			
		||||
    return new RegExp(value.r.p, value.r.f);
 | 
			
		||||
  if (value.m !== undefined)
 | 
			
		||||
    return new Map(innerParseSerializedValue(value.m, handles, refs));
 | 
			
		||||
  if (value.se !== undefined)
 | 
			
		||||
    return new Set(innerParseSerializedValue(value.se, handles, refs));
 | 
			
		||||
 | 
			
		||||
  if (value.a !== undefined) {
 | 
			
		||||
    const result: any[] = [];
 | 
			
		||||
@ -145,6 +149,10 @@ function innerSerializeValue(value: any, handleSerializer: (value: any) => Handl
 | 
			
		||||
    }
 | 
			
		||||
    return { s: `${error.name}: ${error.message}\n${error.stack}` };
 | 
			
		||||
  }
 | 
			
		||||
  if (isMap(value))
 | 
			
		||||
    return { m: innerSerializeValue(Array.from(value), handleSerializer, visitorInfo) };
 | 
			
		||||
  if (isSet(value))
 | 
			
		||||
    return { se: innerSerializeValue(Array.from(value), handleSerializer, visitorInfo) };
 | 
			
		||||
  if (isDate(value))
 | 
			
		||||
    return { d: value.toJSON() };
 | 
			
		||||
  if (isURL(value))
 | 
			
		||||
@ -175,6 +183,14 @@ function innerSerializeValue(value: any, handleSerializer: (value: any) => Handl
 | 
			
		||||
  throw new Error('Unexpected value');
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isMap(obj: any): obj is Map<any, any> {
 | 
			
		||||
  return obj instanceof Map || Object.prototype.toString.call(obj) === '[object Map]';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isSet(obj: any): obj is Set<any> {
 | 
			
		||||
  return obj instanceof Set || Object.prototype.toString.call(obj) === '[object Set]';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
function isRegExp(obj: any): obj is RegExp {
 | 
			
		||||
  return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -58,6 +58,8 @@ scheme.SerializedValue = tObject({
 | 
			
		||||
  d: tOptional(tString),
 | 
			
		||||
  u: tOptional(tString),
 | 
			
		||||
  bi: tOptional(tString),
 | 
			
		||||
  m: tOptional(tType('SerializedValue')),
 | 
			
		||||
  se: tOptional(tType('SerializedValue')),
 | 
			
		||||
  r: tOptional(tObject({
 | 
			
		||||
    p: tString,
 | 
			
		||||
    f: tString,
 | 
			
		||||
 | 
			
		||||
@ -20,6 +20,8 @@ export type SerializedValue =
 | 
			
		||||
    { d: string } |
 | 
			
		||||
    { u: string } |
 | 
			
		||||
    { bi: string } |
 | 
			
		||||
    { m: SerializedValue } |
 | 
			
		||||
    { se: SerializedValue } |
 | 
			
		||||
    { r: { p: string, f: string} } |
 | 
			
		||||
    { a: SerializedValue[], id: number } |
 | 
			
		||||
    { o: { k: string, v: SerializedValue }[], id: number } |
 | 
			
		||||
@ -35,6 +37,14 @@ type VisitorInfo = {
 | 
			
		||||
 | 
			
		||||
export function source() {
 | 
			
		||||
 | 
			
		||||
  function isMap(obj: any): obj is Map<any, any> {
 | 
			
		||||
    return obj instanceof Map || Object.prototype.toString.call(obj) === '[object Map]';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function isSet(obj: any): obj is Set<any> {
 | 
			
		||||
    return obj instanceof Set || Object.prototype.toString.call(obj) === '[object Set]';
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  function isRegExp(obj: any): obj is RegExp {
 | 
			
		||||
    try {
 | 
			
		||||
      return obj instanceof RegExp || Object.prototype.toString.call(obj) === '[object RegExp]';
 | 
			
		||||
@ -94,6 +104,10 @@ export function source() {
 | 
			
		||||
        return new URL(value.u);
 | 
			
		||||
      if ('bi' in value)
 | 
			
		||||
        return BigInt(value.bi);
 | 
			
		||||
      if ('m' in value)
 | 
			
		||||
        return new Map(parseEvaluationResultValue(value.m));
 | 
			
		||||
      if ('se' in value)
 | 
			
		||||
        return new Set(parseEvaluationResultValue(value.se));
 | 
			
		||||
      if ('r' in value)
 | 
			
		||||
        return new RegExp(value.r.p, value.r.f);
 | 
			
		||||
      if ('a' in value) {
 | 
			
		||||
@ -163,6 +177,11 @@ export function source() {
 | 
			
		||||
    if (typeof value === 'bigint')
 | 
			
		||||
      return { bi: value.toString() };
 | 
			
		||||
 | 
			
		||||
    if (isMap(value))
 | 
			
		||||
      return { m: serialize(Array.from(value), handleSerializer, visitorInfo) };
 | 
			
		||||
    if (isSet(value))
 | 
			
		||||
      return { se: serialize(Array.from(value), handleSerializer, visitorInfo) };
 | 
			
		||||
 | 
			
		||||
    if (isError(value)) {
 | 
			
		||||
      const error = value;
 | 
			
		||||
      if (error.stack?.startsWith(error.name + ': ' + error.message)) {
 | 
			
		||||
 | 
			
		||||
@ -180,6 +180,8 @@ export type SerializedValue = {
 | 
			
		||||
  d?: string,
 | 
			
		||||
  u?: string,
 | 
			
		||||
  bi?: string,
 | 
			
		||||
  m?: SerializedValue,
 | 
			
		||||
  se?: SerializedValue,
 | 
			
		||||
  r?: {
 | 
			
		||||
    p: string,
 | 
			
		||||
    f: string,
 | 
			
		||||
 | 
			
		||||
@ -82,6 +82,10 @@ SerializedValue:
 | 
			
		||||
    u: string?
 | 
			
		||||
    # String representation of BigInt.
 | 
			
		||||
    bi: string?
 | 
			
		||||
    # JS representation of Map: [[key1, value1], [key2, value2], ...].
 | 
			
		||||
    m: SerializedValue?
 | 
			
		||||
    # JS representation of Set: [item1, item2, ...].
 | 
			
		||||
    se: SerializedValue?
 | 
			
		||||
    # Regular expression pattern and flags.
 | 
			
		||||
    r:
 | 
			
		||||
      type: object?
 | 
			
		||||
 | 
			
		||||
@ -99,9 +99,14 @@ it('should transfer bigint', async ({ page }) => {
 | 
			
		||||
  expect(await page.evaluate(a => a, 17n)).toBe(17n);
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
it('should transfer maps as empty objects', async ({ page }) => {
 | 
			
		||||
  const result = await page.evaluate(a => a.x.constructor.name + ' ' + JSON.stringify(a.x), { x: new Map([[1, 2]]) });
 | 
			
		||||
  expect(result).toBe('Object {}');
 | 
			
		||||
it('should transfer maps', async ({ page }) => {
 | 
			
		||||
  expect(await page.evaluate(() => new Map([[1, { test: 42n }]]))).toEqual(new Map([[1, { test: 42n }]]));
 | 
			
		||||
  expect(await page.evaluate(a => a, new Map([[1, { test: 17n }]]))).toEqual(new Map([[1, { test: 17n }]]));
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
it('should transfer sets', async ({ page }) => {
 | 
			
		||||
  expect(await page.evaluate(() => new Set([1, { test: 42n }]))).toEqual(new Set([1, { test: 42n }]));
 | 
			
		||||
  expect(await page.evaluate(a => a, new Set([1, { test: 17n }]))).toEqual(new Set([1, { test: 17n }]));
 | 
			
		||||
});
 | 
			
		||||
 | 
			
		||||
it('should modify global environment', async ({ page }) => {
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user