Skip to content

Commit

Permalink
Detect circular references in var_dump (#470)
Browse files Browse the repository at this point in the history
* Detect circular references in var_dump

* Update CHANGELOG.md
  • Loading branch information
kvz authored Apr 5, 2024
1 parent 9da257a commit b3413a4
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 6 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ Ideas that will be planned and find their way into a release at one point
Released: TBA. [Diff](https://github.com/locutusjs/locutus/compare/v2.0.30...main).

- [ ]
- [x] Make var_dump detect circular references (fixes #305)

## v2.0.30

Expand Down
23 changes: 18 additions & 5 deletions src/php/var/var_dump.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,17 @@
const visitedObjects = new Map() // Initialize a map to track visited objects

module.exports = function var_dump() {
// discuss at: https://locutus.io/php/var_dump/
// original by: Brett Zamir (https://brett-zamir.me)
// improved by: Zahlii
// improved by: Brett Zamir (https://brett-zamir.me)
// note 1: For returning a string, use var_export() with the second argument set to true
// test: skip-all
// example 1: var_dump(1)
// returns 1: 'int(1)'
// example 2: const simpleCircular = {}
// example 2: simpleCircular.self = simpleCircular
// example 2: var_dump(simpleCircular)
// returns 2: 'array(1) {\n [self] =>\n Circular Reference Detected\n}\n'

const echo = require('../strings/echo')
let output = ''
Expand Down Expand Up @@ -107,7 +112,7 @@ module.exports = function var_dump() {
return ret
}

const _formatArray = function (obj, curDepth, padVal, padChar) {
const _formatArray = function (obj, curDepth, padVal, padChar, visitedObjects) {
if (curDepth > 0) {
curDepth++
}
Expand All @@ -118,6 +123,14 @@ module.exports = function var_dump() {
let val = ''

if (typeof obj === 'object' && obj !== null) {
if (visitedObjects.has(obj)) {
// Circular reference detected, return a placeholder or a message
return 'Circular Reference Detected\n'
} else {
// Mark this object as visited by adding it to the map
visitedObjects.set(obj, true)
}

if (obj.constructor && _getFuncName(obj.constructor) === 'LOCUTUS_Resource') {
return obj.var_dump()
}
Expand All @@ -142,7 +155,7 @@ module.exports = function var_dump() {
str += key
str += '] =>\n'
str += thickPad
str += _formatArray(objVal, curDepth + 1, padVal, padChar)
str += _formatArray(objVal, curDepth + 1, padVal, padChar, visitedObjects)
} else {
val = _getInnerVal(objVal, thickPad)
str += thickPad
Expand All @@ -161,9 +174,9 @@ module.exports = function var_dump() {
return str
}

output = _formatArray(arguments[0], 0, padVal, padChar)
output = _formatArray(arguments[0], 0, padVal, padChar, visitedObjects)
for (i = 1; i < arguments.length; i++) {
output += '\n' + _formatArray(arguments[i], 0, padVal, padChar)
output += '\n' + _formatArray(arguments[i], 0, padVal, padChar, visitedObjects)
}

echo(output)
Expand Down
10 changes: 9 additions & 1 deletion test/languages/php/var/test-var_dump.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,19 @@ var ini_set = require('../../../../src/php/info/ini_set') // eslint-disable-line
var ini_get = require('../../../../src/php/info/ini_get') // eslint-disable-line no-unused-vars,camelcase
var var_dump = require('../../../../src/php/var/var_dump.js') // eslint-disable-line no-unused-vars,camelcase

describe.skip('src/php/var/var_dump.js (tested in test/languages/php/var/test-var_dump.js)', function () {
describe('src/php/var/var_dump.js (tested in test/languages/php/var/test-var_dump.js)', function () {
it('should pass example 1', function (done) {
var expected = 'int(1)'
var result = var_dump(1)
expect(result).to.deep.equal(expected)
done()
})
it('should pass example 2', function (done) {
var expected = 'array(1) {\n [self] =>\n Circular Reference Detected\n}\n'
const simpleCircular = {}
simpleCircular.self = simpleCircular
var result = var_dump(simpleCircular)
expect(result).to.deep.equal(expected)
done()
})
})

0 comments on commit b3413a4

Please sign in to comment.