Skip to content

Commit 5bc250f

Browse files
committed
[changed] don't clone unspecified object keys
1 parent 069c6fd commit 5bc250f

File tree

6 files changed

+55
-50
lines changed

6 files changed

+55
-50
lines changed

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
"main": "lib/index.js",
66
"scripts": {
77
"test": "npm run build && karma start --single-run",
8+
"tdd": "npm run build && karma start",
89
"clean": "rimaf ./lib/*",
910
"build": "babel src --out-dir lib",
1011
"release": "release"
@@ -24,6 +25,7 @@
2425
"babel-eslint": "^4.1.4",
2526
"babel-loader": "^5.3.2",
2627
"babel-plugin-external-helpers": "^1.1.1",
28+
"benchmark": "^2.0.0",
2729
"chai": "^1.9.1",
2830
"chai-as-promised": "^4.1.1",
2931
"eslint": "^0.24.1",

src/object.js

+30-28
Original file line numberDiff line numberDiff line change
@@ -78,79 +78,81 @@ inherits(ObjectSchema, MixedSchema, {
7878
, value = MixedSchema.prototype._cast.call(schema, _value)
7979

8080
//should ignore nulls here
81-
if( schema._typeCheck(value) ) {
82-
var fields = schema.fields
83-
, strip = schema._option('stripUnknown', _opts) === true
84-
, extra = Object.keys(value).filter( v => schema._nodes.indexOf(v) === -1)
85-
, props = schema._nodes.concat(extra)
81+
if (!schema._typeCheck(value))
82+
return value;
8683

87-
return transform(props, function(obj, prop) {
84+
var fields = schema.fields
85+
, strip = schema._option('stripUnknown', _opts) === true
86+
, extra = Object.keys(value).filter( v => schema._nodes.indexOf(v) === -1)
87+
, props = schema._nodes.concat(extra);
88+
89+
schema.withMutation(() => {
90+
value = transform(props, function(obj, prop) {
8891
var exists = has(value, prop);
8992

90-
if( exists && fields[prop] ){
93+
if (exists && fields[prop]) {
9194
var fieldSchema = childSchema(fields[prop], schema.default(undefined))
9295

9396
obj[prop] = fieldSchema.cast(value[prop], { context: obj })
9497
}
98+
else if (exists && !strip)
99+
obj[prop] = value[prop]
95100

96-
else if( exists && !strip)
97-
obj[prop] = cloneDeep(value[prop])
98-
99-
else if(fields[prop]){
101+
else if(fields[prop]) {
100102
var fieldDefault = fields[prop].default ? fields[prop].default() : undefined
101103

102-
if ( fieldDefault !== undefined)
104+
if (fieldDefault !== undefined)
103105
obj[prop] = fieldDefault
104106
}
105-
106107
}, {})
107-
}
108+
109+
delete schema._default
110+
})
108111

109112
return value
110113
},
111114

112115
_validate(_value, _opts, _state) {
113116
var errors = []
114-
, context, schema, endEarly, recursive;
117+
, state = _state || {}
118+
, context, schema
119+
, endEarly, recursive;
115120

116-
_state = _state || {}
117-
context = _state.parent || (_opts || {}).context
121+
context = state.parent || (_opts || {}).context
118122
schema = this._resolve(context)
119123
endEarly = schema._option('abortEarly', _opts)
120124
recursive = schema._option('recursive', _opts)
121125

122126
return MixedSchema.prototype._validate
123-
.call(this, _value, _opts, _state)
127+
.call(this, _value, _opts, state)
124128
.catch(endEarly ? null : err => {
125129
errors.push(err)
126130
return err.value
127131
})
128132
.then(value => {
129-
if( !recursive || !isObject(value)) { // only iterate though actual objects
133+
if (!recursive || !isObject(value)) { // only iterate though actual objects
130134
if ( errors.length ) throw errors[0]
131135
return value
132136
}
133137

134-
let result = schema._nodes.map(function(key){
135-
var path = (_state.path ? (_state.path + '.') : '') + key
138+
let result = schema._nodes.map(function(key) {
139+
var path = (state.path ? (state.path + '.') : '') + key
136140
, field = childSchema(schema.fields[key], schema)
137141

138142
return field._validate(value[key]
139143
, _opts
140-
, { ..._state, key, path, parent: value })
144+
, { ...state, key, path, parent: value })
141145
})
142146

143147
result = endEarly
144148
? Promise.all(result).catch(scopeError(value))
145-
: collectErrors(result, value, _state.path, errors)
149+
: collectErrors(result, value, state.path, errors)
146150

147151
return result.then(() => value)
148152
})
149-
150-
151153
},
152154

153-
concat(schema){
155+
concat(schema) {
154156
var next = MixedSchema.prototype.concat.call(this, schema)
155157

156158
next._nodes = sortFields(next.fields, next._excludedEdges)
@@ -233,8 +235,8 @@ function unknown(ctx, value) {
233235
function sortFields(fields, excludes = []){
234236
var edges = [], nodes = []
235237

236-
for( var key in fields ) if ( has(fields, key)) {
237-
if ( !~nodes.indexOf(key) ) nodes.push(key)
238+
for (var key in fields) if (has(fields, key)) {
239+
if (!~nodes.indexOf(key)) nodes.push(key)
238240

239241
fields[key]._deps &&
240242
fields[key]._deps.forEach(dep => { //eslint-disable-line no-loop-func

src/string.js

+11-11
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ function StringSchema(){
1515
MixedSchema.call(this, { type: 'string'})
1616

1717
this.transforms.push(function(value) {
18-
if( this.isType(value) ) return value
19-
return value == null ? ''
18+
if (this.isType(value)) return value
19+
return value == null ? ''
2020
: value.toString ? value.toString() : '' + value
2121
})
2222
}
@@ -34,28 +34,28 @@ inherits(StringSchema, MixedSchema, {
3434
},
3535

3636
min(min, msg){
37-
return this.test({
38-
name: 'min',
39-
exclusive: true,
37+
return this.test({
38+
name: 'min',
39+
exclusive: true,
4040
message: msg || locale.min,
4141
params: { min },
42-
test: value => value == null || value.length >= min
42+
test: value => value == null || value.length >= min
4343
})
4444
},
4545

4646
max(max, msg){
47-
return this.test({
48-
name: 'max',
49-
exclusive: true,
47+
return this.test({
48+
name: 'max',
49+
exclusive: true,
5050
message: msg || locale.max,
5151
params: { max },
5252
test: value => value == null || value.length <= max
5353
})
5454
},
5555

5656
matches(regex, msg){
57-
return this.test({
58-
message: msg || locale.matches,
57+
return this.test({
58+
message: msg || locale.matches,
5959
params: { regex },
6060
test: value => value == null || regex.test(value)
6161
})

src/util/clone.js

+11-7
Original file line numberDiff line numberDiff line change
@@ -2,20 +2,25 @@
22
// Copyright (c) 2011, Yahoo Inc.
33
// All rights reserved. https://github.com/hapijs/hoek/blob/master/LICENSE
44

5+
var isSchema = schema => schema && !!schema.__isYupSchema__;
56

67
module.exports = function clone(obj, seen) {
78
var isFirst = !seen
9+
, isImmutable = isSchema(obj) && !isFirst
810

9-
if (typeof obj !== 'object' || obj === null)
11+
if (typeof obj !== 'object' || obj === null || isImmutable)
1012
return obj;
11-
13+
14+
// if (global.REPORT_CLONE && isFirst)
15+
// throw new Error() //console.log('clone')
16+
1217
seen = seen || { orig: [], copy: [] };
1318

1419
var lookup = seen.orig.indexOf(obj);
1520

1621
if (lookup !== -1)
1722
return seen.copy[lookup];
18-
23+
1924
var newObj;
2025
var cloneDeep = false;
2126

@@ -29,8 +34,7 @@ module.exports = function clone(obj, seen) {
2934
else {
3035
var proto = Object.getPrototypeOf(obj);
3136

32-
33-
if (proto !== null && (!proto || (proto.__isYupSchema__ && !isFirst)) ) {
37+
if (proto !== null && !proto) {
3438
newObj = obj;
3539
}
3640
else {
@@ -52,7 +56,7 @@ module.exports = function clone(obj, seen) {
5256

5357
for (var i = 0, il = keys.length; i < il; ++i) {
5458
var key = keys[i];
55-
59+
5660
var descriptor = Object.getOwnPropertyDescriptor(obj, key);
5761

5862
if (descriptor.get || descriptor.set) {
@@ -65,4 +69,4 @@ module.exports = function clone(obj, seen) {
6569
}
6670

6771
return newObj;
68-
}
72+
}

src/util/condition.js

-3
Original file line numberDiff line numberDiff line change
@@ -24,9 +24,6 @@ class Conditional {
2424
if( !options.then && !options.otherwise )
2525
throw new TypeError('either `then:` or `otherwise:` is required for `when()` conditions')
2626

27-
// if( options.then && options.then._type !== type || options.otherwise && options.otherwise._type !== type)
28-
// throw new TypeError(`cannot create polymorphic conditionals, \`then\` and \`otherwise\` must be the same type: ${type}`)
29-
3027
is = typeof is === 'function'
3128
? is : ((is, value) => is === value).bind(null, is)
3229

test/string.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ describe('String types', function(){
7171

7272
inst.isValid('hel').should.eventually.equal(false),
7373

74-
inst.validate('').should.be.rejected.then(function(err){
74+
inst.validate('').should.be.rejected.then(function(err) {
7575
err.errors.length.should.equal(1)
7676
})
7777
])

0 commit comments

Comments
 (0)