(val, key)
| 461 | const { caseless, skipUndefined } = (isContextDefined(this) && this) || {}; |
| 462 | const result = {}; |
| 463 | const assignValue = (val, key) => { |
| 464 | // Skip dangerous property names to prevent prototype pollution |
| 465 | if (key === '__proto__' || key === 'constructor' || key === 'prototype') { |
| 466 | return; |
| 467 | } |
| 468 | |
| 469 | // findKey lowercases the key, so caseless lookup only applies to strings — |
| 470 | // symbol keys are identity-matched. |
| 471 | const targetKey = (caseless && typeof key === 'string' && findKey(result, key)) || key; |
| 472 | // Read via own-prop only — a bare `result[targetKey]` walks the prototype |
| 473 | // chain, so a polluted Object.prototype value could surface here and get |
| 474 | // copied into the merged result. |
| 475 | const existing = hasOwnProperty(result, targetKey) ? result[targetKey] : undefined; |
| 476 | if (isPlainObject(existing) && isPlainObject(val)) { |
| 477 | result[targetKey] = merge(existing, val); |
| 478 | } else if (isPlainObject(val)) { |
| 479 | result[targetKey] = merge({}, val); |
| 480 | } else if (isArray(val)) { |
| 481 | result[targetKey] = val.slice(); |
| 482 | } else if (!skipUndefined || !isUndefined(val)) { |
| 483 | result[targetKey] = val; |
| 484 | } |
| 485 | }; |
| 486 | |
| 487 | for (let i = 0, l = objs.length; i < l; i++) { |
| 488 | const source = objs[i]; |
no test coverage detected