php-serialize
Advanced tools
Comparing version 2.0.1 to 2.1.0
@@ -0,1 +1,5 @@ | ||
## 2.1.0 | ||
- Add support for `encoding` parameter for serialize/unserialize | ||
## 2.0.1 | ||
@@ -2,0 +6,0 @@ |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -10,15 +10,18 @@ Object.defineProperty(exports, "__esModule", { | ||
exports.getClass = getClass; | ||
exports.__PHP_Incomplete_Class = void 0; | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
class __PHP_Incomplete_Class { | ||
constructor(name) { | ||
this.__PHP_Incomplete_Class_Name = name; | ||
} | ||
var __PHP_Incomplete_Class = exports.__PHP_Incomplete_Class = function __PHP_Incomplete_Class(name) { | ||
_classCallCheck(this, __PHP_Incomplete_Class); | ||
} | ||
this.__PHP_Incomplete_Class_Name = name; | ||
}; | ||
exports.__PHP_Incomplete_Class = __PHP_Incomplete_Class; | ||
function getByteLength(contents) { | ||
function getByteLength(contents, options) { | ||
if (typeof Buffer !== 'undefined') { | ||
return Buffer.byteLength(contents, 'utf8'); | ||
return Buffer.byteLength(contents, options.encoding); | ||
} | ||
return encodeURIComponent(contents).replace(/%[A-F\d]{2}/g, 'U').length; | ||
@@ -37,4 +40,5 @@ } | ||
function PhpClass() {} | ||
PhpClass.prototype = prototype; | ||
return PhpClass; | ||
} |
@@ -1,13 +0,12 @@ | ||
'use strict'; | ||
"use strict"; | ||
var _unserialize = require('./unserialize'); | ||
var _unserialize = _interopRequireDefault(require("./unserialize")); | ||
var _unserialize2 = _interopRequireDefault(_unserialize); | ||
var _serialize = _interopRequireDefault(require("./serialize")); | ||
var _serialize = require('./serialize'); | ||
var _serialize2 = _interopRequireDefault(_serialize); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
module.exports = { serialize: _serialize2.default, unserialize: _unserialize2.default }; | ||
module.exports = { | ||
serialize: _serialize.default, | ||
unserialize: _unserialize.default | ||
}; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,10 +6,13 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
var _slicedToArray = function () { function sliceIterator(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"]) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } return function (arr, i) { if (Array.isArray(arr)) { return arr; } else if (Symbol.iterator in Object(arr)) { return sliceIterator(arr, i); } else { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } }; }(); | ||
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _nonIterableRest(); } | ||
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | ||
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance"); } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _iterableToArrayLimit(arr, i) { var _arr = []; var _n = true; var _d = false; var _e = undefined; try { for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) { _arr.push(_s.value); if (i && _arr.length === i) break; } } catch (err) { _d = true; _e = err; } finally { try { if (!_n && _i["return"] != null) _i["return"](); } finally { if (_d) throw _e; } } return _arr; } | ||
var PARSER_TYPES = { | ||
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; } | ||
const PARSER_TYPES = { | ||
N: 'null', | ||
@@ -25,94 +28,85 @@ i: 'int', | ||
var Parser = function () { | ||
function Parser(contents, index) { | ||
_classCallCheck(this, Parser); | ||
class Parser { | ||
constructor(contents, index, options) { | ||
this.contents = contents; | ||
this.index = index; | ||
this.options = options; | ||
} | ||
_createClass(Parser, [{ | ||
key: 'error', | ||
value: function error() { | ||
var message = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 'Syntax Error'; | ||
error(message = 'Syntax Error') { | ||
return new Error(`${message} at index ${this.index} while unserializing payload`); | ||
} | ||
return new Error(message + ' at index ' + this.index + ' while unserializing payload'); | ||
advance(index) { | ||
this.index += index; | ||
} | ||
readAhead(index) { | ||
const contents = this.peekAhead(index); | ||
this.index += index; | ||
return contents; | ||
} | ||
readUntil(expected) { | ||
const index = this.contents.indexOf(expected, this.index); | ||
if (index === -1) { | ||
throw this.error(`Expected '${expected}'`); | ||
} | ||
}, { | ||
key: 'advance', | ||
value: function advance(index) { | ||
this.index += index; | ||
return this.readAhead(index - this.index); | ||
} | ||
peekAhead(index) { | ||
return this.contents.toString(this.options.encoding, this.index, this.index + index); | ||
} | ||
seekExpected(contents) { | ||
const slice = this.readAhead(contents.length); | ||
if (slice !== contents) { | ||
this.index -= contents.length; | ||
throw this.error(`Expected '${contents}'`); | ||
} | ||
}, { | ||
key: 'readAhead', | ||
value: function readAhead(index) { | ||
var contents = this.peekAhead(index); | ||
this.index += index; | ||
return contents; | ||
} | ||
}, { | ||
key: 'readUntil', | ||
value: function readUntil(expected) { | ||
var index = this.contents.indexOf(expected, this.index); | ||
if (index === -1) { | ||
throw this.error('Expected \'' + expected + '\''); | ||
} | ||
return this.readAhead(index - this.index); | ||
} | ||
}, { | ||
key: 'peekAhead', | ||
value: function peekAhead(index) { | ||
return this.contents.toString('utf8', this.index, this.index + index); | ||
} | ||
}, { | ||
key: 'seekExpected', | ||
value: function seekExpected(contents) { | ||
var slice = this.readAhead(contents.length); | ||
if (slice !== contents) { | ||
this.index -= contents.length; | ||
throw this.error('Expected \'' + contents + '\''); | ||
} | ||
} | ||
}, { | ||
key: 'getType', | ||
value: function getType() { | ||
var _readAhead = this.readAhead(2), | ||
_readAhead2 = _slicedToArray(_readAhead, 2), | ||
type = _readAhead2[0], | ||
ps = _readAhead2[1]; | ||
} | ||
var parserType = PARSER_TYPES[type]; | ||
getType() { | ||
const _this$readAhead = this.readAhead(2), | ||
_this$readAhead2 = _slicedToArray(_this$readAhead, 2), | ||
type = _this$readAhead2[0], | ||
ps = _this$readAhead2[1]; | ||
if (!parserType) { | ||
throw this.error('Unknown type'); | ||
} | ||
if (parserType === 'null' ? ps !== ';' : ps !== ':') { | ||
throw this.error(); | ||
} | ||
return parserType; | ||
const parserType = PARSER_TYPES[type]; | ||
if (!parserType) { | ||
throw this.error('Unknown type'); | ||
} | ||
}, { | ||
key: 'getLength', | ||
value: function getLength() { | ||
var length = parseInt(this.readUntil(':'), 10); | ||
if (Number.isNaN(length)) { | ||
throw this.error(); | ||
} | ||
return length; | ||
if (parserType === 'null' ? ps !== ';' : ps !== ':') { | ||
throw this.error(); | ||
} | ||
}, { | ||
key: 'getByLength', | ||
value: function getByLength(startSequence, endSequence, callback) { | ||
var length = this.getLength(); | ||
this.seekExpected(':' + startSequence); | ||
var result = callback(length); | ||
this.seekExpected(endSequence); | ||
return result; | ||
return parserType; | ||
} | ||
getLength() { | ||
const length = parseInt(this.readUntil(':'), 10); | ||
if (Number.isNaN(length)) { | ||
throw this.error(); | ||
} | ||
}]); | ||
return Parser; | ||
}(); | ||
return length; | ||
} | ||
getByLength(startSequence, endSequence, callback) { | ||
const length = this.getLength(); | ||
this.seekExpected(`:${startSequence}`); | ||
const result = callback(length); | ||
this.seekExpected(endSequence); | ||
return result; | ||
} | ||
} | ||
exports.default = Parser; |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,33 +6,26 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | ||
exports.default = serialize; | ||
var _assert = require('assert'); | ||
var _assert = _interopRequireDefault(require("assert")); | ||
var _assert2 = _interopRequireDefault(_assert); | ||
var _helpers = require("./helpers"); | ||
var _helpers = require('./helpers'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function getClassNamespace(item, scope) { | ||
return Object.keys(scope).find(function (key) { | ||
return item instanceof scope[key]; | ||
}) || item.__PHP_Incomplete_Class_Name || item.constructor.name; | ||
return Object.keys(scope).find(key => item instanceof scope[key]) || item.__PHP_Incomplete_Class_Name || item.constructor.name; | ||
} | ||
function serializeObject(item, scope) { | ||
var processed = Array.isArray(item) ? item.map(function (value, index) { | ||
return '' + serialize(index, scope) + serialize(value, scope); | ||
}) : Object.keys(item).map(function (key) { | ||
return '' + serialize(key, scope) + serialize(item[key], scope); | ||
}); | ||
return processed.length + ':{' + processed.join('') + '}'; | ||
const processed = Array.isArray(item) ? item.map((value, index) => `${serialize(index, scope)}${serialize(value, scope)}`) : Object.keys(item).map(key => `${serialize(key, scope)}${serialize(item[key], scope)}`); | ||
return `${processed.length}:{${processed.join('')}}`; | ||
} | ||
function serialize(item) { | ||
var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
function serialize(item, scope = {}, givenOptions = {}) { | ||
const type = typeof item; | ||
const options = Object.assign({}, givenOptions); | ||
var type = typeof item === 'undefined' ? 'undefined' : _typeof(item); | ||
if (typeof options.encoding === 'undefined') { | ||
options.encoding = 'utf8'; | ||
} | ||
@@ -42,28 +35,36 @@ if (item === null) { | ||
} | ||
if (type === 'number') { | ||
if ((0, _helpers.isInteger)(item)) { | ||
return 'i:' + item + ';'; | ||
return `i:${item};`; | ||
} | ||
return 'd:' + item.toString().toUpperCase() + ';'; | ||
return `d:${item.toString().toUpperCase()};`; | ||
} | ||
if (type === 'string') { | ||
return 's:' + (0, _helpers.getByteLength)(item) + ':"' + item + '";'; | ||
return `s:${(0, _helpers.getByteLength)(item, options)}:"${item}";`; | ||
} | ||
if (type === 'boolean') { | ||
return 'b:' + (item ? '1' : '0') + ';'; | ||
return `b:${item ? '1' : '0'};`; | ||
} | ||
if (type !== 'object') { | ||
throw new TypeError('Unexpected type \'' + type + '\' encountered while attempting to serialize'); | ||
throw new TypeError(`Unexpected type '${type}' encountered while attempting to serialize`); | ||
} | ||
if (Array.isArray(item) || item.constructor.name === 'Object') { | ||
return 'a:' + serializeObject(item, scope); | ||
return `a:${serializeObject(item, scope)}`; | ||
} | ||
var constructorName = getClassNamespace(item, scope); | ||
const constructorName = getClassNamespace(item, scope); | ||
if (typeof item.serialize === 'function') { | ||
var serialized = item.serialize(); | ||
(0, _assert2.default)(typeof serialized === 'string', item.constructor.name + '.serialize should return a string'); | ||
return 'C:' + constructorName.length + ':"' + constructorName + '":' + (0, _helpers.getByteLength)(serialized) + ':{' + serialized + '}'; | ||
const serialized = item.serialize(); | ||
(0, _assert.default)(typeof serialized === 'string', `${item.constructor.name}.serialize should return a string`); | ||
return `C:${constructorName.length}:"${constructorName}":${(0, _helpers.getByteLength)(serialized, options)}:{${serialized}}`; | ||
} | ||
return 'O:' + constructorName.length + ':"' + constructorName + '":' + serializeObject(item, scope); | ||
return `O:${constructorName.length}:"${constructorName}":${serializeObject(item, scope)}`; | ||
} |
@@ -1,2 +0,2 @@ | ||
'use strict'; | ||
"use strict"; | ||
@@ -6,19 +6,17 @@ Object.defineProperty(exports, "__esModule", { | ||
}); | ||
exports.default = void 0; | ||
var _assert = require('assert'); | ||
var _assert = _interopRequireDefault(require("assert")); | ||
var _assert2 = _interopRequireDefault(_assert); | ||
var _parser = _interopRequireDefault(require("./parser")); | ||
var _parser = require('./parser'); | ||
var _helpers = require("./helpers"); | ||
var _parser2 = _interopRequireDefault(_parser); | ||
var _helpers = require('./helpers'); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } | ||
function getClassReference(className, scope, strict) { | ||
var container = void 0; | ||
var classReference = scope[className]; | ||
(0, _assert2.default)(classReference || !strict, 'Class ' + className + ' not found in given scope'); | ||
let container; | ||
const classReference = scope[className]; | ||
(0, _assert.default)(classReference || !strict, `Class ${className} not found in given scope`); | ||
if (classReference) { | ||
@@ -29,2 +27,3 @@ container = new ((0, _helpers.getClass)(classReference.prototype))(); | ||
} | ||
return container; | ||
@@ -34,12 +33,19 @@ } | ||
function unserializePairs(parser, length, scope, options) { | ||
var pairs = []; | ||
for (var i = 0; i < length; i += 1) { | ||
var key = unserializeItem(parser, scope, options); | ||
const pairs = []; | ||
for (let i = 0; i < length; i += 1) { | ||
const key = unserializeItem(parser, scope, options); | ||
parser.seekExpected(';'); | ||
var value = unserializeItem(parser, scope, options); | ||
const value = unserializeItem(parser, scope, options); | ||
if (parser.peekAhead(1) === ';') { | ||
parser.advance(1); | ||
} | ||
pairs.push({ key: key, value: value }); | ||
pairs.push({ | ||
key, | ||
value | ||
}); | ||
} | ||
return pairs; | ||
@@ -49,32 +55,30 @@ } | ||
function unserializeItem(parser, scope, options) { | ||
var type = parser.getType(); | ||
const type = parser.getType(); | ||
if (type === 'null') { | ||
return null; | ||
} | ||
if (type === 'int' || type === 'float') { | ||
var value = parser.readUntil(';'); | ||
const value = parser.readUntil(';'); | ||
return type === 'int' ? parseInt(value, 10) : parseFloat(value); | ||
} | ||
if (type === 'boolean') { | ||
var _value = parser.readAhead(1); | ||
return _value === '1'; | ||
const value = parser.readAhead(1); | ||
return value === '1'; | ||
} | ||
if (type === 'string') { | ||
return parser.getByLength('"', '"', function (length) { | ||
return parser.readAhead(length); | ||
}); | ||
return parser.getByLength('"', '"', length => parser.readAhead(length)); | ||
} | ||
if (type === 'array-object') { | ||
var pairs = parser.getByLength('{', '}', function (length) { | ||
return unserializePairs(parser, length, scope, options); | ||
}); | ||
var isArray = pairs.every(function (item) { | ||
return (0, _helpers.isInteger)(item.key); | ||
}); | ||
var result = isArray ? [] : {}; | ||
pairs.forEach(function (_ref) { | ||
var key = _ref.key, | ||
value = _ref.value; | ||
const pairs = parser.getByLength('{', '}', length => unserializePairs(parser, length, scope, options)); | ||
const isArray = pairs.every(item => (0, _helpers.isInteger)(item.key)); | ||
const result = isArray ? [] : {}; | ||
pairs.forEach(function ({ | ||
key, | ||
value | ||
}) { | ||
result[key] = value; | ||
@@ -84,49 +88,50 @@ }); | ||
} | ||
if (type === 'notserializable-class') { | ||
var name = parser.getByLength('"', '"', function (length) { | ||
return parser.readAhead(length); | ||
}); | ||
const name = parser.getByLength('"', '"', length => parser.readAhead(length)); | ||
parser.seekExpected(':'); | ||
var _pairs = parser.getByLength('{', '}', function (length) { | ||
return unserializePairs(parser, length, scope, options); | ||
const pairs = parser.getByLength('{', '}', length => unserializePairs(parser, length, scope, options)); | ||
const result = getClassReference(name, scope, options.strict); | ||
pairs.forEach(function ({ | ||
key, | ||
value | ||
}) { | ||
result[key] = value; | ||
}); | ||
var _result = getClassReference(name, scope, options.strict); | ||
_pairs.forEach(function (_ref2) { | ||
var key = _ref2.key, | ||
value = _ref2.value; | ||
return result; | ||
} | ||
_result[key] = value; | ||
}); | ||
return _result; | ||
} | ||
if (type === 'serializable-class') { | ||
var _name = parser.getByLength('"', '"', function (length) { | ||
return parser.readAhead(length); | ||
}); | ||
const name = parser.getByLength('"', '"', length => parser.readAhead(length)); | ||
parser.seekExpected(':'); | ||
var payload = parser.getByLength('{', '}', function (length) { | ||
return parser.readAhead(length); | ||
}); | ||
var _result2 = getClassReference(_name, scope, options.strict); | ||
if (!(_result2 instanceof _helpers.__PHP_Incomplete_Class)) { | ||
(0, _assert2.default)(_result2.unserialize, 'unserialize not found on class when processing \'' + _name + '\''); | ||
_result2.unserialize(payload); | ||
const payload = parser.getByLength('{', '}', length => parser.readAhead(length)); | ||
const result = getClassReference(name, scope, options.strict); | ||
if (!(result instanceof _helpers.__PHP_Incomplete_Class)) { | ||
(0, _assert.default)(result.unserialize, `unserialize not found on class when processing '${name}'`); | ||
result.unserialize(payload); | ||
} | ||
return _result2; | ||
return result; | ||
} | ||
throw new Error('Invalid type \'' + type + '\' encounterd while unserializing'); | ||
throw new Error(`Invalid type '${type}' encounterd while unserializing`); | ||
} | ||
function unserialize(item) { | ||
var scope = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; | ||
var givenOptions = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : {}; | ||
function unserialize(item, scope = {}, givenOptions = {}) { | ||
const options = Object.assign({}, givenOptions); | ||
var options = Object.assign({}, givenOptions); | ||
if (typeof options.strict === 'undefined') { | ||
options.strict = true; | ||
} | ||
var parser = new _parser2.default(Buffer.from(item), 0); | ||
if (typeof options.encoding === 'undefined') { | ||
options.encoding = 'utf8'; | ||
} | ||
const parser = new _parser.default(Buffer.from(item), 0, options); | ||
return unserializeItem(parser, scope, options); | ||
} | ||
exports.default = unserialize; | ||
var _default = unserialize; | ||
exports.default = _default; |
{ | ||
"name": "php-serialize", | ||
"version": "2.0.1", | ||
"version": "2.1.0", | ||
"description": "PHP serialize/unserialize in Javascript", | ||
@@ -9,5 +9,6 @@ "main": "lib/index.js", | ||
"test:update-php-output": "php spec/serialize.php > spec/serialize.php.out", | ||
"lint": "eslint .", | ||
"lint": "(flow check) && (eslint . ) && (prettier --list-different src/*.js)", | ||
"build": "sb-babel-cli src -o lib", | ||
"watch": "npm run build -- -w" | ||
"watch": "npm run build -- -w", | ||
"prepare": "npm run build" | ||
}, | ||
@@ -25,24 +26,11 @@ "repository": { | ||
"devDependencies": { | ||
"@babel/plugin-proposal-class-properties": "^7.0.0-rc.1", | ||
"ava": "1.0.0-beta.7", | ||
"babel-core": "^6.26.3", | ||
"babel-preset-steelbrain": "^5.0.0", | ||
"eslint-config-steelbrain": "^5.0.2", | ||
"flow-bin": "^0.79.0", | ||
"sb-babel-cli": "^0.1.2" | ||
"@babel/core": "^7.2.2", | ||
"@babel/preset-env": "^7.2.3", | ||
"@babel/preset-flow": "^7.0.0", | ||
"ava": "^1.0.1", | ||
"eslint-config-steelbrain": "^6.0.0", | ||
"flow-bin": "^0.89.0", | ||
"sb-babel-cli": "^1.0.3" | ||
}, | ||
"ava": { | ||
"babel": { | ||
"testOptions": { | ||
"babelrc": false, | ||
"plugins": [ | ||
"@babel/proposal-class-properties" | ||
], | ||
"presets": [ | ||
"module:ava/stage-4" | ||
] | ||
} | ||
} | ||
}, | ||
"dependencies": {} | ||
} |
@@ -39,4 +39,12 @@ # PHP-Serialize | ||
class Serializable { | ||
serialize(item: any, phpToJsScope: Object = {}): string | ||
unserialize(item: string, scope: Object = {}, options: { strict: boolean } = { strict: false }): any | ||
serialize( | ||
item: any, | ||
phpToJsScope: Object = {}, | ||
options: { encoding: 'utf8' | 'binary' } = { encoding: 'utf8' } | ||
): string | ||
unserialize( | ||
item: string, | ||
scope: Object = {}, | ||
options: { strict: boolean, encoding: 'utf8' | 'binary' } = { strict: false, encoding: 'utf8' } | ||
): any | ||
} | ||
@@ -43,0 +51,0 @@ ``` |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
55
15888
280
1