From c5240d6fc7ff8d4e6d4f1648040c79a53437e359 Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Sun, 2 Mar 2025 18:49:26 -0600 Subject: [PATCH 1/2] feat: Allow field names to start with underscore --- integration/test/ParseObjectTest.js | 4 ++-- src/ParseObject.ts | 4 ++-- src/__tests__/ParseObject-test.js | 6 ++++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index 05977687c..b6ec74b8e 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -547,7 +547,7 @@ describe('Parse Object', () => { }); it('cannot create invalid key names', async () => { - const error = new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: "foo^bar"`); + const error = new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid field name: foo^bar'); const item = new Parse.Object('Item'); expect(() => { item.set({ 'foo^bar': 'baz' }); @@ -559,7 +559,7 @@ describe('Parse Object', () => { const item = new Parse.Object('Item'); expect(() => { item.set({ foobar: 'baz', 'foo^bar': 'baz' }); - }).toThrow(new Parse.Error(Parse.Error.INVALID_KEY_NAME, `Invalid key name: "foo^bar"`)); + }).toThrow(new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid field name: foo^bar')); }); it('can unset fields', done => { diff --git a/src/ParseObject.ts b/src/ParseObject.ts index c53930757..68e554b6a 100644 --- a/src/ParseObject.ts +++ b/src/ParseObject.ts @@ -1099,8 +1099,8 @@ class ParseObject { return new ParseError(ParseError.OTHER_CAUSE, 'ACL must be a Parse ACL.'); } for (const key in attrs) { - if (!/^[A-Za-z][0-9A-Za-z_.]*$/.test(key)) { - return new ParseError(ParseError.INVALID_KEY_NAME, `Invalid key name: "${key}"`); + if (!/^[A-Za-z_][0-9A-Za-z_.]*$/.test(key)) { + return new ParseError(ParseError.INVALID_KEY_NAME, `Invalid field name: ${key}`); } } return false; diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index 565b57c96..c488dade7 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -965,7 +965,7 @@ describe('ParseObject', () => { o.validate({ 'invalid!key': 12, }) - ).toEqual(new ParseError(ParseError.INVALID_KEY_NAME, `Invalid key name: "invalid!key"`)); + ).toEqual(new ParseError(ParseError.INVALID_KEY_NAME, 'Invalid field name: invalid!key')); expect( o.validate({ @@ -988,7 +988,7 @@ describe('ParseObject', () => { expect(o.set('ACL', { '*': { read: true, write: false } })).toBe(o); expect(() => { o.set('$$$', 'o_O'); - }).toThrow(new ParseError(ParseError.INVALID_KEY_NAME, `Invalid key name: "$$$"`)); + }).toThrow(new ParseError(ParseError.INVALID_KEY_NAME, 'Invalid field name: $$$')); }); it('ignores validation if ignoreValidation option is passed to set()', () => { @@ -1003,6 +1003,8 @@ describe('ParseObject', () => { expect(o.isValid()).toBe(true); o.set('someKey', 'someValue'); expect(o.isValid()).toBe(true); + o.set('_internalField', 'allow_underscore'); + expect(o.isValid()).toBe(true); o._finishFetch({ objectId: 'O3', 'invalid!key': 'oops', From f5d60ae45ffa80068e7ac5600275885ccf41cc3a Mon Sep 17 00:00:00 2001 From: Diamond Lewis Date: Wed, 5 Mar 2025 10:39:02 -0600 Subject: [PATCH 2/2] clean up tests --- integration/test/ParseObjectTest.js | 4 ++-- src/ParseObject.ts | 2 +- src/__tests__/ParseObject-test.js | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/integration/test/ParseObjectTest.js b/integration/test/ParseObjectTest.js index b6ec74b8e..a58de1c65 100644 --- a/integration/test/ParseObjectTest.js +++ b/integration/test/ParseObjectTest.js @@ -547,7 +547,7 @@ describe('Parse Object', () => { }); it('cannot create invalid key names', async () => { - const error = new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid field name: foo^bar'); + const error = new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid key name: foo^bar'); const item = new Parse.Object('Item'); expect(() => { item.set({ 'foo^bar': 'baz' }); @@ -559,7 +559,7 @@ describe('Parse Object', () => { const item = new Parse.Object('Item'); expect(() => { item.set({ foobar: 'baz', 'foo^bar': 'baz' }); - }).toThrow(new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid field name: foo^bar')); + }).toThrow(new Parse.Error(Parse.Error.INVALID_KEY_NAME, 'Invalid key name: foo^bar')); }); it('can unset fields', done => { diff --git a/src/ParseObject.ts b/src/ParseObject.ts index 68e554b6a..208e503c7 100644 --- a/src/ParseObject.ts +++ b/src/ParseObject.ts @@ -1100,7 +1100,7 @@ class ParseObject { } for (const key in attrs) { if (!/^[A-Za-z_][0-9A-Za-z_.]*$/.test(key)) { - return new ParseError(ParseError.INVALID_KEY_NAME, `Invalid field name: ${key}`); + return new ParseError(ParseError.INVALID_KEY_NAME, `Invalid key name: ${key}`); } } return false; diff --git a/src/__tests__/ParseObject-test.js b/src/__tests__/ParseObject-test.js index c488dade7..127b7a053 100644 --- a/src/__tests__/ParseObject-test.js +++ b/src/__tests__/ParseObject-test.js @@ -965,7 +965,7 @@ describe('ParseObject', () => { o.validate({ 'invalid!key': 12, }) - ).toEqual(new ParseError(ParseError.INVALID_KEY_NAME, 'Invalid field name: invalid!key')); + ).toEqual(new ParseError(ParseError.INVALID_KEY_NAME, 'Invalid key name: invalid!key')); expect( o.validate({ @@ -988,7 +988,7 @@ describe('ParseObject', () => { expect(o.set('ACL', { '*': { read: true, write: false } })).toBe(o); expect(() => { o.set('$$$', 'o_O'); - }).toThrow(new ParseError(ParseError.INVALID_KEY_NAME, 'Invalid field name: $$$')); + }).toThrow(new ParseError(ParseError.INVALID_KEY_NAME, 'Invalid key name: $$$')); }); it('ignores validation if ignoreValidation option is passed to set()', () => {