Skip to content

Commit

Permalink
fix: update serializeUploadOptions option to based on options runtime…
Browse files Browse the repository at this point in the history
… types
  • Loading branch information
AllanZhengYP committed Jan 22, 2025
1 parent f0ae76e commit 914d289
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 10 deletions.
2 changes: 1 addition & 1 deletion packages/aws-amplify/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -515,7 +515,7 @@
"name": "[Storage] uploadData (S3)",
"path": "./dist/esm/storage/index.mjs",
"import": "{ uploadData }",
"limit": "22.95 kB"
"limit": "22.99 kB"
}
]
}
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,12 @@ const mockListParts = jest.mocked(listParts);
const mockHeadObject = jest.mocked(headObject);
const mockCalculateContentCRC32 = jest.mocked(calculateContentCRC32);

// Hack to make sure jest mocked defaultStorage is not serializable. So it will not change the options hash.
Object.setPrototypeOf(
defaultStorage,
Object.getPrototypeOf(jest.requireActual('@aws-amplify/core').defaultStorage),
);

const disableAssertionFlag = true;

const MB = 1024 * 1024;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,22 +99,42 @@ const listCachedUploadTasks = async (
};

/**
* Serialize the uploadData API options to string so it can be hashed.
* Serialize the uploadData API options to string so it can be hashed. The following options will be OMITTED from the
* result. It only checks the top-level options assuming we do not use unserializable types in nested properties by
* design.
* * undefined
* * bigint
* * function
* * symbol
* * class instances except for Array.
*/
export const serializeUploadOptions = (
options: UploadDataWithPathInputWithAdvancedOptions['options'] & {
resumableUploadsCache?: KeyValueStorageInterface;
} = {},
): string => {
const unserializableOptionProperties: string[] = [
'onProgress',
'resumableUploadsCache', // Internally injected implementation not set by customers
'locationCredentialsProvider', // Internally injected implementation not set by customers
] satisfies (keyof typeof options)[];
const isSerializable = (value: any): boolean => {
const valueType = typeof value;
if (['bigint', 'function', 'symbol', 'undefined'].includes(valueType)) {
return false;
}
if (valueType === 'object') {
if (
value === null ||
Object.getPrototypeOf(value) === Object.prototype ||
Object.getPrototypeOf(value) === Array.prototype
) {
return true; // null/array/plain objects
}

return false;
}

return true; // string/number/boolean
};

const serializableOptions = Object.fromEntries(
Object.entries(options).filter(
([key]) => !unserializableOptionProperties.includes(key),
),
Object.entries(options).filter(([_, value]) => isSerializable(value)),
);

return JSON.stringify(serializableOptions);
Expand Down

0 comments on commit 914d289

Please # to comment.