From 494f87d434932a8baab23cd64bbcfe9f5c600b1b Mon Sep 17 00:00:00 2001 From: Hans Larsen Date: Tue, 26 Sep 2017 12:45:27 -0700 Subject: [PATCH] feat(@angular-devkit/core): add support for schema in template Before we were messing with ownKeys to only return defined properties, but that has the side effect that those will not work inside a "with() {}" clause, which is what templates are using. We now need a serialize symbol if we want to only serialize defined properties, but for now parity with @ngtools/json-schema is not a priority. --- .../templates/javascript/prop-object.ejs | 18 +++++++++++++++--- .../schema/serializers/1.0.javascript_spec.ts | 5 ++--- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/packages/angular_devkit/core/src/json/schema/serializers/templates/javascript/prop-object.ejs b/packages/angular_devkit/core/src/json/schema/serializers/templates/javascript/prop-object.ejs index 8242cc1fa5..eb2412e3cb 100644 --- a/packages/angular_devkit/core/src/json/schema/serializers/templates/javascript/prop-object.ejs +++ b/packages/angular_devkit/core/src/json/schema/serializers/templates/javascript/prop-object.ejs @@ -37,9 +37,13 @@ const handlers = Object.create(null); } %> +const objectFunctions = { + hasOwnProperty(name) { return objectProxyHandler.has(null, name); }, +}; + let defined = false; -const proxy = new Proxy({}, { +const objectProxyHandler = { isExtensible() { return false; }, has(target, prop) { return (prop in handlers && handlers[prop].isDefined()) @@ -54,6 +58,9 @@ const proxy = new Proxy({}, { if (prop in handlers) { return handlers[prop].get(); } + if (prop in objectFunctions) { + return objectFunctions[prop]; + } return undefined; }, set(target, prop, v) { @@ -90,15 +97,20 @@ const proxy = new Proxy({}, { getOwnPropertyDescriptor(target, prop) { if (prop in handlers) { return { configurable: true, enumerable: true }; + } else if (additionalPropertyHandler && prop in additionalPropertyHandler) { + return { configurable: true, enumerable: true }; } }, ownKeys(target) { return [].concat( - Object.keys(handlers).filter(function(key) { return handlers[key].isDefined(); }), + Object.keys(handlers), additionalPropertyHandler ? Object.keys(additionalProperties) : [] ); }, -}); +}; + + +const proxy = new Proxy({}, objectProxyHandler); const objectHandler = { set(v) { diff --git a/tests/@angular_devkit/core/json/schema/serializers/1.0.javascript_spec.ts b/tests/@angular_devkit/core/json/schema/serializers/1.0.javascript_spec.ts index ec8e7d8038..9d37e38db4 100644 --- a/tests/@angular_devkit/core/json/schema/serializers/1.0.javascript_spec.ts +++ b/tests/@angular_devkit/core/json/schema/serializers/1.0.javascript_spec.ts @@ -36,7 +36,7 @@ export function works(registry: schema.JsonSchemaRegistry, schema: any) { v.objectKey1.objectKey = { stringKey: 'str2' }; expect(v.objectKey1.objectKey.stringKey).toBe('str2'); - expect(Object.keys(v.objectKey1)).toEqual(['stringKey', 'objectKey']); + expect(Object.keys(v.objectKey1)).toEqual(['stringKey', 'stringKeyDefault', 'objectKey']); } @@ -55,9 +55,8 @@ export function accessUndefined(registry: schema.JsonSchemaRegistry, schema: any expect(v.objectKey1).not.toBe(undefined); expect(v.objectKey1.stringKey).toBe('hello'); expect(v.objectKey1.numberKey).toBe(undefined); - expect(v).toEqual({ 'requiredKey': 1, 'objectKey1': { 'stringKey': 'hello' } }); v.objectKey1.stringKey = undefined; - expect(v).toEqual({ 'requiredKey': 1 }); + expect(v.objectKey1.stringKey).toBe(undefined); expect(v.stringKeyDefault).toBe('defaultValue'); expect(v.objectKey1.stringKeyDefault).toBe('defaultValue2');