198 lines
4.7 KiB
JavaScript
198 lines
4.7 KiB
JavaScript
|
|
/**
|
||
|
|
* Copyright (c) 2018-present, Facebook, Inc. All rights reserved.
|
||
|
|
*
|
||
|
|
* This source code is licensed under the MIT license found in the
|
||
|
|
* LICENSE file in the root directory of this source tree.
|
||
|
|
*
|
||
|
|
*
|
||
|
|
*/
|
||
|
|
|
||
|
|
'use strict';
|
||
|
|
|
||
|
|
Object.defineProperty(exports, '__esModule', {
|
||
|
|
value: true
|
||
|
|
});
|
||
|
|
exports.deserialize = deserialize;
|
||
|
|
exports.serialize = serialize;
|
||
|
|
exports.readFileSync = readFileSync;
|
||
|
|
exports.writeFileSync = writeFileSync;
|
||
|
|
|
||
|
|
var _fs;
|
||
|
|
|
||
|
|
function _load_fs() {
|
||
|
|
return (_fs = _interopRequireDefault(require('fs')));
|
||
|
|
}
|
||
|
|
|
||
|
|
var _v;
|
||
|
|
|
||
|
|
function _load_v() {
|
||
|
|
return (_v = _interopRequireDefault(require('v8')));
|
||
|
|
}
|
||
|
|
|
||
|
|
function _interopRequireDefault(obj) {
|
||
|
|
return obj && obj.__esModule ? obj : {default: obj};
|
||
|
|
}
|
||
|
|
|
||
|
|
// JSON and V8 serializers are both stable when it comes to compatibility. The
|
||
|
|
// current JSON specification is well defined in RFC 8259, and V8 ensures that
|
||
|
|
// the versions are compatible by encoding the serialization version in the own
|
||
|
|
// generated buffer.
|
||
|
|
|
||
|
|
const JS_TYPE = '__$t__';
|
||
|
|
const JS_VALUE = '__$v__';
|
||
|
|
const JS_VF = '__$f__';
|
||
|
|
|
||
|
|
function replacer(key, value) {
|
||
|
|
// NaN cannot be in a switch statement, because NaN !== NaN.
|
||
|
|
if (Number.isNaN(value)) {
|
||
|
|
return {[JS_TYPE]: 'n'};
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (value) {
|
||
|
|
case undefined:
|
||
|
|
return {[JS_TYPE]: 'u'};
|
||
|
|
|
||
|
|
case +Infinity:
|
||
|
|
return {[JS_TYPE]: '+'};
|
||
|
|
|
||
|
|
case -Infinity:
|
||
|
|
return {[JS_TYPE]: '-'};
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (value && value.constructor) {
|
||
|
|
case Date:
|
||
|
|
return {[JS_TYPE]: 'd', [JS_VALUE]: value.getTime()};
|
||
|
|
|
||
|
|
case RegExp:
|
||
|
|
return {[JS_TYPE]: 'r', [JS_VALUE]: value.source, [JS_VF]: value.flags};
|
||
|
|
|
||
|
|
case Set:
|
||
|
|
return {[JS_TYPE]: 's', [JS_VALUE]: Array.from(value)};
|
||
|
|
|
||
|
|
case Map:
|
||
|
|
return {[JS_TYPE]: 'm', [JS_VALUE]: Array.from(value)};
|
||
|
|
|
||
|
|
case Buffer:
|
||
|
|
return {[JS_TYPE]: 'b', [JS_VALUE]: value.toString('latin1')};
|
||
|
|
}
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
function reviver(key, value) {
|
||
|
|
if (!value || (typeof value !== 'object' && !value.hasOwnProperty(JS_TYPE))) {
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
switch (value[JS_TYPE]) {
|
||
|
|
case 'u':
|
||
|
|
return undefined;
|
||
|
|
|
||
|
|
case 'n':
|
||
|
|
return NaN;
|
||
|
|
|
||
|
|
case '+':
|
||
|
|
return +Infinity;
|
||
|
|
|
||
|
|
case '-':
|
||
|
|
return -Infinity;
|
||
|
|
|
||
|
|
case 'd':
|
||
|
|
return new Date(value[JS_VALUE]);
|
||
|
|
|
||
|
|
case 'r':
|
||
|
|
return new RegExp(value[JS_VALUE], value[JS_VF]);
|
||
|
|
|
||
|
|
case 's':
|
||
|
|
return new Set(value[JS_VALUE]);
|
||
|
|
|
||
|
|
case 'm':
|
||
|
|
return new Map(value[JS_VALUE]);
|
||
|
|
|
||
|
|
case 'b':
|
||
|
|
return Buffer.from(value[JS_VALUE], 'latin1');
|
||
|
|
}
|
||
|
|
|
||
|
|
return value;
|
||
|
|
}
|
||
|
|
|
||
|
|
function jsonStringify(content) {
|
||
|
|
// Not pretty, but the ES JSON spec says that "toJSON" will be called before
|
||
|
|
// getting into your replacer, so we have to remove them beforehand. See
|
||
|
|
// https://www.ecma-international.org/ecma-262/#sec-serializejsonproperty
|
||
|
|
// section 2.b for more information.
|
||
|
|
|
||
|
|
const dateToJSON = Date.prototype.toJSON;
|
||
|
|
const bufferToJSON = Buffer.prototype.toJSON;
|
||
|
|
|
||
|
|
/* eslint-disable no-extend-native */
|
||
|
|
|
||
|
|
try {
|
||
|
|
// $FlowFixMe: intentional removal of "toJSON" property.
|
||
|
|
Date.prototype.toJSON = undefined;
|
||
|
|
// $FlowFixMe: intentional removal of "toJSON" property.
|
||
|
|
Buffer.prototype.toJSON = undefined;
|
||
|
|
|
||
|
|
return JSON.stringify(content, replacer);
|
||
|
|
} finally {
|
||
|
|
// $FlowFixMe: intentional assignment of "toJSON" property.
|
||
|
|
Date.prototype.toJSON = dateToJSON;
|
||
|
|
// $FlowFixMe: intentional assignment of "toJSON" property.
|
||
|
|
Buffer.prototype.toJSON = bufferToJSON;
|
||
|
|
}
|
||
|
|
|
||
|
|
/* eslint-enable no-extend-native */
|
||
|
|
}
|
||
|
|
|
||
|
|
function jsonParse(content) {
|
||
|
|
return JSON.parse(content, reviver);
|
||
|
|
}
|
||
|
|
|
||
|
|
// In memory functions.
|
||
|
|
|
||
|
|
function deserialize(buffer) {
|
||
|
|
// $FlowFixMe - Node 8+ only
|
||
|
|
return (_v || _load_v()).default.deserialize
|
||
|
|
? (_v || _load_v()).default.deserialize(buffer)
|
||
|
|
: jsonParse(buffer.toString('utf8'));
|
||
|
|
}
|
||
|
|
|
||
|
|
function serialize(content) {
|
||
|
|
// $FlowFixMe - Node 8+ only
|
||
|
|
return (_v || _load_v()).default.serialize
|
||
|
|
? (_v || _load_v()).default.serialize(content)
|
||
|
|
: Buffer.from(jsonStringify(content));
|
||
|
|
}
|
||
|
|
|
||
|
|
// Synchronous filesystem functions.
|
||
|
|
|
||
|
|
function readFileSync(filePath) {
|
||
|
|
// $FlowFixMe - Node 8+ only
|
||
|
|
return (_v || _load_v()).default.deserialize
|
||
|
|
? (_v || _load_v()).default.deserialize(
|
||
|
|
(_fs || _load_fs()).default.readFileSync(filePath)
|
||
|
|
)
|
||
|
|
: jsonParse((_fs || _load_fs()).default.readFileSync(filePath, 'utf8'));
|
||
|
|
}
|
||
|
|
|
||
|
|
function writeFileSync(filePath, content) {
|
||
|
|
// $FlowFixMe - Node 8+ only
|
||
|
|
return (_v || _load_v()).default.serialize
|
||
|
|
? (_fs || _load_fs()).default.writeFileSync(
|
||
|
|
filePath,
|
||
|
|
(_v || _load_v()).default.serialize(content)
|
||
|
|
)
|
||
|
|
: (_fs || _load_fs()).default.writeFileSync(
|
||
|
|
filePath,
|
||
|
|
jsonStringify(content),
|
||
|
|
'utf8'
|
||
|
|
);
|
||
|
|
}
|
||
|
|
|
||
|
|
exports.default = {
|
||
|
|
deserialize,
|
||
|
|
readFileSync,
|
||
|
|
serialize,
|
||
|
|
writeFileSync
|
||
|
|
};
|