Skip to content

Commit 308a6fd

Browse files
committed
feat: tmp
1 parent 67afd8d commit 308a6fd

File tree

1 file changed

+48
-45
lines changed

1 file changed

+48
-45
lines changed

test/utils/serialize-javascript.ts

Lines changed: 48 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -63,10 +63,18 @@ export function stringify(value: any, options?: StringifyOptions): string {
6363
}
6464
const result: SerializedResult = {
6565
source: JSON.stringify(serialized),
66-
patches,
67-
descriptors,
66+
patches: serializeJavascriptRecursively(patches, { parentPath: [], circularRefs: new WeakMap(), debug }) as Patch[],
67+
descriptors: serializeJavascriptRecursively(descriptors, {
68+
parentPath: [],
69+
circularRefs: new WeakMap(),
70+
}) as DescriptorMeta[],
6871
types,
6972
};
73+
if (debug) {
74+
console.log('patches: ', patches);
75+
console.log('descriptors: ', descriptors);
76+
console.log('types: ', types);
77+
}
7078
return JSON.stringify(result);
7179
}
7280

@@ -114,6 +122,7 @@ function serializeJavascriptRecursively(
114122
};
115123
if (typeof source === 'object') {
116124
if (checkCircularRef()) return undefined;
125+
// todo: 这两个字段没有被删除 "[Symbol.for('[keys]')]": undefined, "[Symbol.for('[values]')]": undefined,
117126
// todo: 修复e2e测试
118127
// todo: 优先判断对象是否有toJson()方法
119128
// todo: parse时,需要判断是否有fromJson()方法,如果有,则调用该方法进行反序列化
@@ -229,7 +238,6 @@ export function parse(input: string, options?: ParseOptions) {
229238
...options,
230239
closure,
231240
variablePrefix: VP,
232-
enablePatches: true,
233241
});
234242
} catch (error) {
235243
console.error(error);
@@ -241,14 +249,15 @@ function executeDeserialize(result: SerializedResult, options: InternalParseOpti
241249
const { variablePrefix: VP = VariablePrefix, closure, get = getByPath, debug, prettyPrint = true } = options ?? {};
242250
const code = getDeserializeJavascriptCode(result, options);
243251
if (debug) {
244-
const printSourceCode = getDeserializeJavascriptCode(result, { ...options, isPrint: true });
252+
const printSourceCode = getDeserializeJavascriptCode(result, { ...options, isPrinting: true });
245253
const prettyPrintCode = `\`${printSourceCode.replace(/`/g, '\\`').replace(/\$\{/g, '\\${')}\``;
246254
const realCode = `'${printSourceCode.replace(/\n/g, '\\n').replace(/'/g, "\\'")}'`;
247255
const printCode = prettyPrint ? prettyPrintCode : realCode;
248256
console.log(
249257
'-------------- deserializeCode --------------\n',
250-
`${getByPath.toString()}
251-
new Function('${VP}context', '${VP}options', ${printCode})(${closure ? 'closure' : 'undefined'}, { get: getByPath });`,
258+
`new Function('${VP}context', '${VP}options', ${printCode})(${closure ? 'closure' : 'undefined'}, { get: getByPath });
259+
${getByPath.toString()}
260+
`,
252261
'closure =',
253262
closure
254263
);
@@ -270,32 +279,16 @@ function getDeserializeJavascriptCode(result: SerializedResult, options: Interna
270279
endTag: ET = DefaultEndTag,
271280
variablePrefix: VP = VariablePrefix,
272281
closure,
273-
enablePatches = true,
274-
isPrint,
282+
isPrinting,
275283
} = options ?? {};
276284
const { source: sourceCode, patches, descriptors, types } = result;
277285
// console.log('deserializeJavascript', str, sourceCode);
278-
const escapeSingleQuote = (str: string) => str.replace(/'/g, isPrint ? "\\\\'" : "\\'");
286+
const escapeSingleQuote = (str: string) => str.replace(/'/g, isPrinting ? "\\\\'" : "\\'");
279287
const content = `${closure ? `const { ${Object.keys(closure ?? {}).join(', ')} } = ${VP}context || {};` : ''}
280288
const { get } = ${VP}options;
281289
const deserializeResult = (\n${decodeFormat(sourceCode, { startTag: ST, endTag: ET })}\n);
282290
const types = ${decodeFormat(JSON.stringify(types), { startTag: ST, endTag: ET })};
283-
const patches = ${
284-
enablePatches
285-
? decodeFormat(
286-
JSON.stringify(
287-
patches.map(({ path, ref }) => {
288-
// replace the context with ref
289-
return {
290-
path,
291-
context: ref,
292-
};
293-
})
294-
),
295-
{ startTag: ST, endTag: ET }
296-
)
297-
: '[]'
298-
};
291+
const patches = ${decodeFormat(JSON.stringify(patches), { startTag: ST, endTag: ET })};
299292
const descriptors = ${decodeFormat(
300293
JSON.stringify(
301294
descriptors.map((d) => ({
@@ -325,7 +318,7 @@ function getDeserializeJavascriptCode(result: SerializedResult, options: Interna
325318
function restoreOriginalTypes(obj, types = []) {
326319
// Apply types to the deserialized object
327320
types.forEach(({ path, type, metadata }) => {
328-
const value = path && path.length ? get(obj, path) : obj;
321+
const value = get(obj, path);
329322
const keyName = path && path.length ? path[path.length - 1] : undefined;
330323
const parent = path && path.length ? get(obj, path.slice(0, -1)) : null;
331324
if (value && parent && parent[keyName] === value) {
@@ -367,7 +360,7 @@ function getDeserializeJavascriptCode(result: SerializedResult, options: Interna
367360
function restorePatches(obj, patches = []) {
368361
// Apply patches to the deserialized object
369362
patches.forEach(({ path, context }) => {
370-
const sourceObj = path && path.length ? get(obj, path) : obj;
363+
const sourceObj = get(obj, path);
371364
if (sourceObj) {
372365
const sourceKeys = getFullKeys(sourceObj);
373366
getFullKeys(context).forEach((key) => {
@@ -384,12 +377,12 @@ function getDeserializeJavascriptCode(result: SerializedResult, options: Interna
384377
if (typeof obj === 'object') {
385378
Object.keys(obj).forEach((key) => {
386379
if (
387-
key.match(new RegExp('^${escapeRegExp(SymbolKeyRegExps[0], { escapeTwice: isPrint, format: escapeSingleQuote })}$')) ||
388-
key.match(new RegExp('^${escapeRegExp(SymbolKeyRegExps[1], { escapeTwice: isPrint, format: escapeSingleQuote })}$'))
380+
key.match(new RegExp('^${escapeRegExp(SymbolKeyRegExps[0], { escapeTwice: isPrinting, format: escapeSingleQuote })}$')) ||
381+
key.match(new RegExp('^${escapeRegExp(SymbolKeyRegExps[1], { escapeTwice: isPrinting, format: escapeSingleQuote })}$'))
389382
) {
390383
const symbolExpr = key
391-
.replace(new RegExp('^${escapeRegExp(SymbolKeyPrefixRegExp, { escapeTwice: isPrint })}'), '')
392-
.replace(new RegExp('${escapeRegExp(SymbolKeySuffixRegExp, { escapeTwice: isPrint })}$'), '');
384+
.replace(new RegExp('^${escapeRegExp(SymbolKeyPrefixRegExp, { escapeTwice: isPrinting })}'), '')
385+
.replace(new RegExp('${escapeRegExp(SymbolKeySuffixRegExp, { escapeTwice: isPrinting })}$'), '');
393386
const symbolKey = new Function('return ' + symbolExpr)();
394387
obj[symbolKey] = obj[key];
395388
delete obj[key];
@@ -407,7 +400,7 @@ function getDeserializeJavascriptCode(result: SerializedResult, options: Interna
407400
function restoreDescriptors(obj, descriptors = []) {
408401
// Apply descriptors to the deserialized object
409402
descriptors.forEach(({ ownerPath, key, descriptor: sourceDescriptor }) => {
410-
const owner = ownerPath && ownerPath.length ? get(obj, ownerPath) : undefined;
403+
const owner = get(obj, ownerPath);
411404
if (owner) {
412405
const value = owner[key];
413406
const copied = { ...sourceDescriptor };
@@ -522,26 +515,38 @@ function expandPrototypeChainRecursively(
522515
if (typeof key === 'symbol') {
523516
key = getSymbolFieldName(key) ?? '';
524517
}
525-
const copied = {
526-
...descriptor,
527-
get: descriptor.get ? stringToBase64(serializeFunction(descriptor.get.toString())!) : undefined,
528-
set: descriptor.set ? stringToBase64(serializeFunction(descriptor.set.toString())!) : undefined,
529-
};
530-
delete copied.value;
518+
// eslint-disable-next-line @typescript-eslint/no-unused-vars
519+
const { value: _value, ...copied } = descriptor;
520+
const result = copied as DescriptorMeta['descriptor'];
521+
if (descriptor.get) {
522+
result.get = stringToBase64(serializeFunction(descriptor.get.toString())!);
523+
}
524+
if (descriptor.set) {
525+
result.set = stringToBase64(serializeFunction(descriptor.set.toString())!);
526+
}
531527
descriptors.push({
532528
ownerPath: paths,
533529
key,
534-
descriptor: copied,
530+
descriptor: result,
535531
});
536532
}
537533
};
538534
const assign = (source: Record<string | symbol, any>) => {
539-
const sourceDescriptors = Object.getOwnPropertyDescriptors(proto);
535+
const sourceDescriptors = Object.getOwnPropertyDescriptors(source);
540536
getFullKeys(source).forEach((key) => {
541537
const descriptor = sourceDescriptors[key];
542538
const destDescriptor = destDescriptors[key as string];
543-
// If the descriptor is not readable, skip it
539+
let index: number;
540+
// Ignore array length and indecies
541+
if (
542+
Array.isArray(source) &&
543+
typeof key === 'string' &&
544+
(key === 'length' || ((index = Number(key)) >= 0 && index < source.length))
545+
) {
546+
return;
547+
}
544548
if (descriptor && !descriptor.get && !('value' in descriptor)) {
549+
// If the descriptor is not readable, skip it
545550
return;
546551
}
547552
// If the destination descriptor is not writable, skip it
@@ -551,7 +556,7 @@ function expandPrototypeChainRecursively(
551556
try {
552557
result[key] = source[key];
553558
} catch (error) {
554-
// not raise error
559+
// Silent failure
555560
}
556561
checkDescriptor(key, descriptor);
557562
});
@@ -740,7 +745,6 @@ type PathType = string | number | symbol;
740745
interface Patch {
741746
path: PathType[];
742747
context: any;
743-
ref?: string;
744748
}
745749
interface DescriptorMeta {
746750
ownerPath: PathType[];
@@ -804,8 +808,7 @@ export type ParseOptions = Pick<StringifyOptions, 'startTag' | 'endTag' | 'varia
804808
};
805809

806810
interface InternalParseOptions extends ParseOptions {
807-
enablePatches?: boolean;
808-
isPrint?: boolean;
811+
isPrinting?: boolean;
809812
}
810813

811814
export type ExpandPrototypeChainOptions = {

0 commit comments

Comments
 (0)