Skip to content

Commit 914d289

Browse files
committed
fix: update serializeUploadOptions option to based on options runtime types
1 parent f0ae76e commit 914d289

File tree

3 files changed

+36
-10
lines changed

3 files changed

+36
-10
lines changed

packages/aws-amplify/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,7 +515,7 @@
515515
"name": "[Storage] uploadData (S3)",
516516
"path": "./dist/esm/storage/index.mjs",
517517
"import": "{ uploadData }",
518-
"limit": "22.95 kB"
518+
"limit": "22.99 kB"
519519
}
520520
]
521521
}

packages/storage/__tests__/providers/s3/apis/internal/uploadData/multipartHandlers.test.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,12 @@ const mockListParts = jest.mocked(listParts);
5757
const mockHeadObject = jest.mocked(headObject);
5858
const mockCalculateContentCRC32 = jest.mocked(calculateContentCRC32);
5959

60+
// Hack to make sure jest mocked defaultStorage is not serializable. So it will not change the options hash.
61+
Object.setPrototypeOf(
62+
defaultStorage,
63+
Object.getPrototypeOf(jest.requireActual('@aws-amplify/core').defaultStorage),
64+
);
65+
6066
const disableAssertionFlag = true;
6167

6268
const MB = 1024 * 1024;

packages/storage/src/providers/s3/apis/internal/uploadData/multipart/uploadCache.ts

Lines changed: 29 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -99,22 +99,42 @@ const listCachedUploadTasks = async (
9999
};
100100

101101
/**
102-
* Serialize the uploadData API options to string so it can be hashed.
102+
* Serialize the uploadData API options to string so it can be hashed. The following options will be OMITTED from the
103+
* result. It only checks the top-level options assuming we do not use unserializable types in nested properties by
104+
* design.
105+
* * undefined
106+
* * bigint
107+
* * function
108+
* * symbol
109+
* * class instances except for Array.
103110
*/
104111
export const serializeUploadOptions = (
105112
options: UploadDataWithPathInputWithAdvancedOptions['options'] & {
106113
resumableUploadsCache?: KeyValueStorageInterface;
107114
} = {},
108115
): string => {
109-
const unserializableOptionProperties: string[] = [
110-
'onProgress',
111-
'resumableUploadsCache', // Internally injected implementation not set by customers
112-
'locationCredentialsProvider', // Internally injected implementation not set by customers
113-
] satisfies (keyof typeof options)[];
116+
const isSerializable = (value: any): boolean => {
117+
const valueType = typeof value;
118+
if (['bigint', 'function', 'symbol', 'undefined'].includes(valueType)) {
119+
return false;
120+
}
121+
if (valueType === 'object') {
122+
if (
123+
value === null ||
124+
Object.getPrototypeOf(value) === Object.prototype ||
125+
Object.getPrototypeOf(value) === Array.prototype
126+
) {
127+
return true; // null/array/plain objects
128+
}
129+
130+
return false;
131+
}
132+
133+
return true; // string/number/boolean
134+
};
135+
114136
const serializableOptions = Object.fromEntries(
115-
Object.entries(options).filter(
116-
([key]) => !unserializableOptionProperties.includes(key),
117-
),
137+
Object.entries(options).filter(([_, value]) => isSerializable(value)),
118138
);
119139

120140
return JSON.stringify(serializableOptions);

0 commit comments

Comments
 (0)