Skip to content

Commit 652e019

Browse files
committed
Use singular Object.defineProperty if possible
If multiple properties are defined, we still use `Object.defineProperties`. Else we now use `Object.defineProperty`.
1 parent d0c394f commit 652e019

File tree

5 files changed

+82
-30
lines changed

5 files changed

+82
-30
lines changed

fixtures/object-define-properties-reference/input.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,12 @@ export default ((
77
}
88
) =>
99
($0['assignment'] = Object.defineProperties($0, {
10+
['__proto__']: {
11+
value: $0,
12+
configurable: true,
13+
enumerable: true,
14+
writable: true
15+
},
1016
configurable: {
1117
value: $0,
1218
configurable: true
@@ -18,6 +24,9 @@ export default ((
1824
writable: {
1925
value: $1,
2026
writable: true
27+
},
28+
[Symbol.for('global')]: {
29+
value: {}
2130
}
2231
})))()
2332

fixtures/object-define-properties/input.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,10 @@ export default Object.defineProperties(
55
string: 'Hello'
66
},
77
{
8+
['__proto__']: {
9+
value: {},
10+
configurable: true
11+
},
812
configurable: {
913
value: 'Only configurable',
1014
configurable: true
@@ -16,6 +20,9 @@ export default Object.defineProperties(
1620
writable: {
1721
value: 'Only writable',
1822
writable: true
23+
},
24+
[Symbol.for('global')]: {
25+
value: {}
1926
}
2027
}
2128
)
@@ -29,6 +36,10 @@ const withoutPreserveReferences = Object.defineProperties(
2936
string: 'Hello'
3037
},
3138
{
39+
['__proto__']: {
40+
value: {},
41+
configurable: true
42+
},
3243
configurable: {
3344
value: 'Only configurable',
3445
configurable: true
@@ -40,6 +51,9 @@ const withoutPreserveReferences = Object.defineProperties(
4051
writable: {
4152
value: 'Only writable',
4253
writable: true
54+
},
55+
[Symbol.for('global')]: {
56+
value: {}
4357
}
4458
}
4559
)
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// Used as input
2+
// { preserveReferences: true }
3+
export default Object.defineProperty(
4+
{
5+
string: 'Hello',
6+
['__proto__']: {}
7+
},
8+
Symbol.for('global'),
9+
{
10+
value: ''
11+
}
12+
)
13+
14+
// -------------------------------------------------------------------------------------------------
15+
16+
// Default output
17+
// { preserveReferences: false }
18+
const withoutPreserveReferences = Object.defineProperty(
19+
{
20+
string: 'Hello',
21+
['__proto__']: {}
22+
},
23+
Symbol.for('global'),
24+
{
25+
value: ''
26+
}
27+
)

fixtures/object-proto-property-recursive/input.js

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,11 @@ export default ((
99
name: '$0'
1010
}
1111
) => (
12-
Object.defineProperties($1, {
13-
['__proto__']: {
14-
value: $0,
15-
configurable: true,
16-
enumerable: true,
17-
writable: true
18-
}
12+
Object.defineProperty($1, '__proto__', {
13+
value: $0,
14+
configurable: true,
15+
enumerable: true,
16+
writable: true
1917
}),
2018
$0
2119
))()

src/estree-util-value-to-estree.ts

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ export function valueToEstree(value: unknown, options: Options = {}): Expression
806806
}
807807

808808
const object = val as Record<string | symbol, unknown>
809-
const propertyDescriptors: Property[] = []
809+
const propertyDescriptors: [string | symbol, ObjectExpression][] = []
810810
for (const key of Reflect.ownKeys(val)) {
811811
// TODO [>=4] Throw an error for getters.
812812
const child = object[key]
@@ -823,29 +823,28 @@ export function valueToEstree(value: unknown, options: Options = {}): Expression
823823
if (writable) {
824824
propertyDescriptor.push(property('writable', literal(true)))
825825
}
826-
propertyDescriptors.push(
827-
property(key, {
828-
type: 'ObjectExpression',
829-
properties: propertyDescriptor
830-
})
831-
)
826+
propertyDescriptors.push([
827+
key,
828+
{ type: 'ObjectExpression', properties: propertyDescriptor }
829+
])
832830
} else if (
833831
context &&
834832
childContext &&
835833
namedContexts.indexOf(childContext) >= namedContexts.indexOf(context)
836834
) {
837835
if (key === '__proto__') {
838-
propertyDescriptors.push(
839-
property(key, {
836+
propertyDescriptors.push([
837+
key,
838+
{
840839
type: 'ObjectExpression',
841840
properties: [
842841
property('value', generate(child)),
843842
property('configurable', literal(true)),
844843
property('enumerable', literal(true)),
845844
property('writable', literal(true))
846845
]
847-
})
848-
)
846+
}
847+
])
849848
} else {
850849
childContext.assignment = {
851850
type: 'AssignmentExpression',
@@ -871,24 +870,29 @@ export function valueToEstree(value: unknown, options: Options = {}): Expression
871870
}
872871

873872
if (propertyDescriptors.length) {
874-
if (!context) {
875-
return methodCall(identifier('Object'), 'defineProperties', [
876-
objectExpression,
873+
let name: string
874+
let args: Expression[]
875+
876+
if (propertyDescriptors.length === 1) {
877+
const [[key, expression]] = propertyDescriptors
878+
name = 'defineProperty'
879+
args = [typeof key === 'string' ? literal(key) : symbolToEstree(key), expression]
880+
} else {
881+
name = 'defineProperties'
882+
args = [
877883
{
878884
type: 'ObjectExpression',
879-
properties: propertyDescriptors
885+
properties: propertyDescriptors.map(([key, expression]) => property(key, expression))
880886
}
881-
])
887+
]
888+
}
889+
890+
if (!context) {
891+
return methodCall(identifier('Object'), name, [objectExpression, ...args])
882892
}
883893

884894
context.assignment = replaceAssignment(
885-
methodCall(identifier('Object'), 'defineProperties', [
886-
identifier(context.name!),
887-
{
888-
type: 'ObjectExpression',
889-
properties: propertyDescriptors
890-
}
891-
]),
895+
methodCall(identifier('Object'), name, [identifier(context.name!), ...args]),
892896
context.assignment
893897
)
894898
}

0 commit comments

Comments
 (0)