Skip to content

Commit

Permalink
fix: avoid referenced object manipulation (#275) (#280)
Browse files Browse the repository at this point in the history
* wip: try collapsing retrieved ui5 obj

* feat: collapse, avoid cylic

first flatten the retrieved ui5 object,
then clone it, avoiding cylic references

* fix: rm deletes, but collapse

- introduce collapseObject for flattening the inheritance Prototype
  this avoids deletion of original object's properties,
  causing unintended side effects
- rm unused window.wdi5...
  - isCyclic
  - removeCyclic
- should fix #275
  • Loading branch information
vobu authored Jun 20, 2022
1 parent a22aac0 commit a069544
Show file tree
Hide file tree
Showing 2 changed files with 23 additions and 58 deletions.
20 changes: 8 additions & 12 deletions client-side-js/executeControlMethod.js
Original file line number Diff line number Diff line change
Expand Up @@ -53,21 +53,17 @@ async function clientSide_executeControlMethod(webElement, methodName, args) {
// allows method chaining
!(result instanceof sap.ui.core.Control)
) {
// object, replacer function
// create usefull content from result
while (window.wdi5.isCyclic(result)) {
result = JSON.parse(
JSON.stringify(
window.wdi5.removeCyclic(result),
window.wdi5.getCircularReplacer()
)
)
}
// flatten the prototype so we have all funcs available
const collapsed = window.wdi5.collapseObject(result)
// exclude cyclic references
const collapsedAndNonCyclic = JSON.parse(
JSON.stringify(collapsed, window.wdi5.getCircularReplacer())
)
done({
status: 0,
result: result,
result: collapsedAndNonCyclic,
returnType: "result",
nonCircularResultObject: result
nonCircularResultObject: collapsedAndNonCyclic
})
} else {
// check if of control to verify if the method result is a different control
Expand Down
61 changes: 15 additions & 46 deletions client-side-js/injectUI5.js
Original file line number Diff line number Diff line change
Expand Up @@ -247,58 +247,27 @@ async function clientSide_injectUI5(config, waitForUI5Timeout) {
return controlMethodsToProxy
}

window.wdi5.isCyclic = (obj) => {
var seenObjects = []

function detect(obj) {
if (obj && typeof obj === "object") {
if (seenObjects.indexOf(obj) !== -1) {
return true
}
seenObjects.push(obj)
for (var key in obj) {
if (obj.hasOwnProperty(key) && detect(obj[key])) {
console.log(obj, "cycle at " + key)
return true
}
}
}
return false
}

return detect(obj)
}

window.wdi5.removeCyclic = (obj) => {
var seenObjects = []

function detect(obj) {
if (obj && typeof obj === "object") {
if (seenObjects.indexOf(obj) !== -1) {
return obj
}
seenObjects.push(obj)
for (var key in obj) {
if (obj.hasOwnProperty(key) && detect(obj[key])) {
console.log(obj, "cycle at " + key)
console.warn(`deleted: ${key}`)
delete obj[key]
return obj
}
}
} else {
console.log(`removed ${typeof obj}`)
}
return obj
/**
* flatten all functions and properties on the Prototype directly into the returned object
* @param {object} obj
* @returns {object} all functions and properties of the inheritance chain in a flat structure
*/
window.wdi5.collapseObject = (obj) => {
let protoChain = []
let proto = obj
while (proto !== null) {
protoChain.unshift(proto)
proto = Object.getPrototypeOf(proto)
}

return detect(obj)
let collapsedObj = {}
protoChain.forEach((prop) => Object.assign(collapsedObj, prop))
return collapsedObj
}

/**
* used as a replacer function in JSON.stringify
* removes circular references in an object
* @returns
* all credit to https://bobbyhadz.com/blog/javascript-typeerror-converting-circular-structure-to-json
*/
window.wdi5.getCircularReplacer = () => {
const seen = new WeakSet()
Expand Down

0 comments on commit a069544

Please sign in to comment.