From 61cb3a4b5f43717caedd1e81dcd689a338d406f3 Mon Sep 17 00:00:00 2001 From: Romain Marcadier-Muller Date: Fri, 28 Sep 2018 16:39:41 +0200 Subject: [PATCH] fix(kernel): Return object literals as references (#249) Use the javascript `Proxy` class to coalesce object literals to an interface type, allowing them to be returned by reference instead of by value. Introduces a test in the `jsii-kernel` to demonstrate the feature works as intended. Fixes #248 Fixes awslabs/aws-cdk#774 --- packages/jsii-calc/lib/compliance.ts | 8 ++ packages/jsii-calc/test/assembly.jsii | 35 ++++- packages/jsii-kernel/lib/kernel.ts | 135 +++++++++++++++++- packages/jsii-kernel/test/test.kernel.ts | 17 +++ packages/jsii-kernel/tsconfig.json | 4 +- .../.jsii | 35 ++++- .../ClassWithMutableObjectLiteralProperty.cs | 27 ++++ .../IMutableObjectLiteral.cs | 15 ++ .../MutableObjectLiteral.cs | 14 ++ .../MutableObjectLiteralProxy.cs | 19 +++ .../amazon/jsii/tests/calculator/$Module.java | 2 + ...ClassWithMutableObjectLiteralProperty.java | 21 +++ .../calculator/MutableObjectLiteral.java | 72 ++++++++++ .../expected.jsii-calc/sphinx/jsii-calc.rst | 67 +++++++++ packages/jsii-runtime/package-lock.json | 47 ++++++ packages/jsii-runtime/package.json | 1 + packages/jsii-runtime/webpack.config.js | 9 +- 17 files changed, 517 insertions(+), 11 deletions(-) create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ClassWithMutableObjectLiteralProperty.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IMutableObjectLiteral.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/MutableObjectLiteral.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/MutableObjectLiteralProxy.cs create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ClassWithMutableObjectLiteralProperty.java create mode 100644 packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/MutableObjectLiteral.java diff --git a/packages/jsii-calc/lib/compliance.ts b/packages/jsii-calc/lib/compliance.ts index 09990ed8af..db640cb841 100644 --- a/packages/jsii-calc/lib/compliance.ts +++ b/packages/jsii-calc/lib/compliance.ts @@ -887,3 +887,11 @@ export class AbstractClassReturner { } } } + +export interface MutableObjectLiteral { + value: string; +} + +export class ClassWithMutableObjectLiteralProperty { + public mutableObject: MutableObjectLiteral = { value: 'default' }; +} diff --git a/packages/jsii-calc/test/assembly.jsii b/packages/jsii-calc/test/assembly.jsii index e312a04915..4297289ffa 100644 --- a/packages/jsii-calc/test/assembly.jsii +++ b/packages/jsii-calc/test/assembly.jsii @@ -1018,6 +1018,23 @@ } ] }, + "jsii-calc.ClassWithMutableObjectLiteralProperty": { + "assembly": "jsii-calc", + "fqn": "jsii-calc.ClassWithMutableObjectLiteralProperty", + "initializer": { + "initializer": true + }, + "kind": "class", + "name": "ClassWithMutableObjectLiteralProperty", + "properties": [ + { + "name": "mutableObject", + "type": { + "fqn": "jsii-calc.MutableObjectLiteral" + } + } + ] + }, "jsii-calc.DefaultedConstructorArgument": { "assembly": "jsii-calc", "fqn": "jsii-calc.DefaultedConstructorArgument", @@ -1883,6 +1900,22 @@ } ] }, + "jsii-calc.MutableObjectLiteral": { + "assembly": "jsii-calc", + "datatype": true, + "fqn": "jsii-calc.MutableObjectLiteral", + "kind": "interface", + "name": "MutableObjectLiteral", + "properties": [ + { + "abstract": true, + "name": "value", + "type": { + "primitive": "string" + } + } + ] + }, "jsii-calc.Negate": { "assembly": "jsii-calc", "base": { @@ -3230,5 +3263,5 @@ } }, "version": "0.7.6", - "fingerprint": "ecDtx3DHVZi7UjyCDhGncg4jbSRaD536bUyh6YzAxlY=" + "fingerprint": "DFShLmIJQmPjTv5Dmz4JoBKqoCtAyifD1RpCuHo+sEc=" } diff --git a/packages/jsii-kernel/lib/kernel.ts b/packages/jsii-kernel/lib/kernel.ts index 867f4d5d00..62fc59418e 100644 --- a/packages/jsii-kernel/lib/kernel.ts +++ b/packages/jsii-kernel/lib/kernel.ts @@ -14,6 +14,8 @@ import { TOKEN_DATE, TOKEN_ENUM, TOKEN_REF } from './api'; */ const OBJID_PROP = '$__jsii__objid__$'; const FQN_PROP = '$__jsii__fqn__$'; +const PROXIES_PROP = '$__jsii__proxies__$'; +const PROXY_REFERENT_PROP = '$__jsii__proxy_referent__$'; /** * A special FQN that can be used to create empty javascript objects. @@ -149,9 +151,14 @@ export class Kernel { const { objref } = req; this._debug('del', objref); - this._findObject(objref); // make sure object exists + const obj = this._findObject(objref); // make sure object exists delete this.objects[objref[TOKEN_REF]]; + if (obj[PROXY_REFERENT_PROP]) { + // De-register the proxy if this was a proxy... + delete obj[PROXY_REFERENT_PROP][PROXIES_PROP][obj[FQN_PROP]]; + } + return { }; } @@ -923,12 +930,20 @@ export class Kernel { // so the client receives a real object. if (typeof(v) === 'object' && targetType && spec.isNamedTypeReference(targetType)) { this._debug('coalescing to', targetType); - const newObjRef = this._create({ fqn: targetType.fqn }); - const newObj = this._findObject(newObjRef); - for (const k of Object.keys(v)) { - newObj[k] = v[k]; + /* + * We "cache" proxy instances in [PROXIES_PROP] so we can return an + * identical object reference upon multiple accesses of the same + * object literal under the same exposed type. This results in a + * behavior that is more consistent with class instances. + */ + const proxies: Proxies = v[PROXIES_PROP] = v[PROXIES_PROP] || {}; + if (!proxies[targetType.fqn]) { + const handler = new KernelProxyHandler(v); + const proxy = new Proxy(v, handler); + // _createObjref will set the FQN_PROP & OBJID_PROP on the proxy. + proxies[targetType.fqn] = { objRef: this._createObjref(proxy, targetType.fqn), handler }; } - return newObjRef; + return proxies[targetType.fqn].objRef; } // date (https://stackoverflow.com/a/643827/737957) @@ -1135,3 +1150,111 @@ function mapSource(err: Error, sourceMaps: { [assm: string]: SourceMapConsumer } return frame; } } + +type ObjectKey = string | number | symbol; +/** + * A Proxy handler class to support mutation of the returned object literals, as + * they may "embody" several different interfaces. The handler is in particular + * responsible to make sure the ``FQN_PROP`` and ``OBJID_PROP`` do not get set + * on the ``referent`` object, for this would cause subsequent accesses to + * possibly return incorrect object references. + */ +class KernelProxyHandler implements ProxyHandler { + private readonly ownProperties: { [key: string]: any } = {}; + + /** + * @param referent the "real" value that will be returned. + */ + constructor(public readonly referent: any) { + /* + * Proxy-properties must exist as non-configurable & writable on the + * referent, otherwise the Proxy will not allow returning ``true`` in + * response to ``defineProperty``. + */ + for (const prop of [FQN_PROP, OBJID_PROP]) { + Object.defineProperty(referent, prop, { + configurable: false, + enumerable: false, + writable: true, + value: undefined + }); + } + } + + public defineProperty(target: any, property: ObjectKey, attributes: PropertyDescriptor): boolean { + switch (property) { + case FQN_PROP: + case OBJID_PROP: + return Object.defineProperty(this.ownProperties, property, attributes); + default: + return Object.defineProperty(target, property, attributes); + } + } + + public deleteProperty(target: any, property: ObjectKey): boolean { + switch (property) { + case FQN_PROP: + case OBJID_PROP: + delete this.ownProperties[property]; + break; + default: + delete target[property]; + } + return true; + } + + public getOwnPropertyDescriptor(target: any, property: ObjectKey): PropertyDescriptor | undefined { + switch (property) { + case FQN_PROP: + case OBJID_PROP: + return Object.getOwnPropertyDescriptor(this.ownProperties, property); + default: + return Object.getOwnPropertyDescriptor(target, property); + } + } + + public get(target: any, property: ObjectKey): any { + switch (property) { + // Magical property for the proxy, so we can tell it's one... + case PROXY_REFERENT_PROP: + return this.referent; + case FQN_PROP: + case OBJID_PROP: + return this.ownProperties[property]; + default: + return target[property]; + } + } + + public set(target: any, property: ObjectKey, value: any): boolean { + switch (property) { + case FQN_PROP: + case OBJID_PROP: + this.ownProperties[property] = value; + break; + default: + target[property] = value; + } + return true; + } + + public has(target: any, property: ObjectKey): boolean { + switch (property) { + case FQN_PROP: + case OBJID_PROP: + return property in this.ownProperties; + default: + return property in target; + } + } + + public ownKeys(target: any): ObjectKey[] { + return Reflect.ownKeys(target).concat(Reflect.ownKeys(this.ownProperties)); + } +} + +type Proxies = { [fqn: string]: ProxyReference }; +interface ProxyReference { + objRef: api.ObjRef; + handler: KernelProxyHandler; +} diff --git a/packages/jsii-kernel/test/test.kernel.ts b/packages/jsii-kernel/test/test.kernel.ts index 92a963e86f..1e93c27bca 100644 --- a/packages/jsii-kernel/test/test.kernel.ts +++ b/packages/jsii-kernel/test/test.kernel.ts @@ -873,6 +873,23 @@ defineTest('node.js standard library', async (test, sandbox) => { { result: "6a2da20943931e9834fc12cfe5bb47bbd9ae43489a30726962b576f4e3993e50" }); }); +// @see awslabs/jsii#248 +defineTest('object literals are returned by reference', async (test, sandbox) => { + const objref = sandbox.create({ fqn: 'jsii-calc.ClassWithMutableObjectLiteralProperty' }); + const property = sandbox.get({ objref, property: 'mutableObject' }).value; + + const newValue = 'Bazinga!1!'; + sandbox.set({ objref: property, property: 'value', value: newValue }); + + test.equal(newValue, + sandbox.get({ + objref: sandbox.get({ objref, property: 'mutableObject' }).value, + property: 'value' + }).value); + + sandbox.del({ objref: property }); +}); + const testNames: { [name: string]: boolean } = { }; async function createCalculatorSandbox(name: string) { diff --git a/packages/jsii-kernel/tsconfig.json b/packages/jsii-kernel/tsconfig.json index 6f8f29cf64..907de24775 100644 --- a/packages/jsii-kernel/tsconfig.json +++ b/packages/jsii-kernel/tsconfig.json @@ -44,8 +44,8 @@ /* Source Map Options */ // "sourceRoot": "./", /* Specify the location where debugger should locate TypeScript files instead of source locations. */ // "mapRoot": "./", /* Specify the location where debugger should locate map files instead of generated locations. */ - // "inlineSourceMap": false, /* Emit a single file with source maps instead of having a separate file. */ - // "inlineSources": false, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ + "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */ + "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */ /* Experimental Options */ "experimentalDecorators": true /* Enables experimental support for ES7 decorators. */ diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii index e312a04915..4297289ffa 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/.jsii @@ -1018,6 +1018,23 @@ } ] }, + "jsii-calc.ClassWithMutableObjectLiteralProperty": { + "assembly": "jsii-calc", + "fqn": "jsii-calc.ClassWithMutableObjectLiteralProperty", + "initializer": { + "initializer": true + }, + "kind": "class", + "name": "ClassWithMutableObjectLiteralProperty", + "properties": [ + { + "name": "mutableObject", + "type": { + "fqn": "jsii-calc.MutableObjectLiteral" + } + } + ] + }, "jsii-calc.DefaultedConstructorArgument": { "assembly": "jsii-calc", "fqn": "jsii-calc.DefaultedConstructorArgument", @@ -1883,6 +1900,22 @@ } ] }, + "jsii-calc.MutableObjectLiteral": { + "assembly": "jsii-calc", + "datatype": true, + "fqn": "jsii-calc.MutableObjectLiteral", + "kind": "interface", + "name": "MutableObjectLiteral", + "properties": [ + { + "abstract": true, + "name": "value", + "type": { + "primitive": "string" + } + } + ] + }, "jsii-calc.Negate": { "assembly": "jsii-calc", "base": { @@ -3230,5 +3263,5 @@ } }, "version": "0.7.6", - "fingerprint": "ecDtx3DHVZi7UjyCDhGncg4jbSRaD536bUyh6YzAxlY=" + "fingerprint": "DFShLmIJQmPjTv5Dmz4JoBKqoCtAyifD1RpCuHo+sEc=" } diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ClassWithMutableObjectLiteralProperty.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ClassWithMutableObjectLiteralProperty.cs new file mode 100644 index 0000000000..ba4858aa12 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/ClassWithMutableObjectLiteralProperty.cs @@ -0,0 +1,27 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiClass(typeof(ClassWithMutableObjectLiteralProperty), "jsii-calc.ClassWithMutableObjectLiteralProperty", "[]")] + public class ClassWithMutableObjectLiteralProperty : DeputyBase + { + public ClassWithMutableObjectLiteralProperty(): base(new DeputyProps(new object[]{})) + { + } + + protected ClassWithMutableObjectLiteralProperty(ByRefValue reference): base(reference) + { + } + + protected ClassWithMutableObjectLiteralProperty(DeputyProps props): base(props) + { + } + + [JsiiProperty("mutableObject", "{\"fqn\":\"jsii-calc.MutableObjectLiteral\"}")] + public virtual IMutableObjectLiteral MutableObject + { + get => GetInstanceProperty(); + set => SetInstanceProperty(value); + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IMutableObjectLiteral.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IMutableObjectLiteral.cs new file mode 100644 index 0000000000..50776bf6d2 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/IMutableObjectLiteral.cs @@ -0,0 +1,15 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiInterface(typeof(IMutableObjectLiteral), "jsii-calc.MutableObjectLiteral")] + public interface IMutableObjectLiteral + { + [JsiiProperty("value", "{\"primitive\":\"string\"}")] + string Value + { + get; + set; + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/MutableObjectLiteral.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/MutableObjectLiteral.cs new file mode 100644 index 0000000000..0313dfa532 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/MutableObjectLiteral.cs @@ -0,0 +1,14 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + public class MutableObjectLiteral : DeputyBase, IMutableObjectLiteral + { + [JsiiProperty("value", "{\"primitive\":\"string\"}", true)] + public string Value + { + get; + set; + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/MutableObjectLiteralProxy.cs b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/MutableObjectLiteralProxy.cs new file mode 100644 index 0000000000..7564f1904c --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/dotnet/Amazon.JSII.Tests.CalculatorPackageId/Amazon/JSII/Tests/CalculatorNamespace/MutableObjectLiteralProxy.cs @@ -0,0 +1,19 @@ +using Amazon.JSII.Runtime.Deputy; + +namespace Amazon.JSII.Tests.CalculatorNamespace +{ + [JsiiTypeProxy(typeof(IMutableObjectLiteral), "jsii-calc.MutableObjectLiteral")] + internal sealed class MutableObjectLiteralProxy : DeputyBase, IMutableObjectLiteral + { + private MutableObjectLiteralProxy(ByRefValue reference): base(reference) + { + } + + [JsiiProperty("value", "{\"primitive\":\"string\"}")] + public string Value + { + get => GetInstanceProperty(); + set => SetInstanceProperty(value); + } + } +} \ No newline at end of file diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java index a0bd08be2b..e173852e15 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/$Module.java @@ -29,6 +29,7 @@ protected Class resolveClass(final String fqn) throws ClassNotFoundException case "jsii-calc.BinaryOperation": return software.amazon.jsii.tests.calculator.BinaryOperation.class; case "jsii-calc.Calculator": return software.amazon.jsii.tests.calculator.Calculator.class; case "jsii-calc.CalculatorProps": return software.amazon.jsii.tests.calculator.CalculatorProps.class; + case "jsii-calc.ClassWithMutableObjectLiteralProperty": return software.amazon.jsii.tests.calculator.ClassWithMutableObjectLiteralProperty.class; case "jsii-calc.DefaultedConstructorArgument": return software.amazon.jsii.tests.calculator.DefaultedConstructorArgument.class; case "jsii-calc.DerivedClassHasNoProperties.Base": return software.amazon.jsii.tests.calculator.DerivedClassHasNoProperties.Base.class; case "jsii-calc.DerivedClassHasNoProperties.Derived": return software.amazon.jsii.tests.calculator.DerivedClassHasNoProperties.Derived.class; @@ -51,6 +52,7 @@ protected Class resolveClass(final String fqn) throws ClassNotFoundException case "jsii-calc.JSObjectLiteralToNativeClass": return software.amazon.jsii.tests.calculator.JSObjectLiteralToNativeClass.class; case "jsii-calc.JavaReservedWords": return software.amazon.jsii.tests.calculator.JavaReservedWords.class; case "jsii-calc.Multiply": return software.amazon.jsii.tests.calculator.Multiply.class; + case "jsii-calc.MutableObjectLiteral": return software.amazon.jsii.tests.calculator.MutableObjectLiteral.class; case "jsii-calc.Negate": return software.amazon.jsii.tests.calculator.Negate.class; case "jsii-calc.NodeStandardLibrary": return software.amazon.jsii.tests.calculator.NodeStandardLibrary.class; case "jsii-calc.NumberGenerator": return software.amazon.jsii.tests.calculator.NumberGenerator.class; diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ClassWithMutableObjectLiteralProperty.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ClassWithMutableObjectLiteralProperty.java new file mode 100644 index 0000000000..6e2fbe4411 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/ClassWithMutableObjectLiteralProperty.java @@ -0,0 +1,21 @@ +package software.amazon.jsii.tests.calculator; + +@javax.annotation.Generated(value = "jsii-pacmak") +@software.amazon.jsii.Jsii(module = software.amazon.jsii.tests.calculator.$Module.class, fqn = "jsii-calc.ClassWithMutableObjectLiteralProperty") +public class ClassWithMutableObjectLiteralProperty extends software.amazon.jsii.JsiiObject { + protected ClassWithMutableObjectLiteralProperty(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + public ClassWithMutableObjectLiteralProperty() { + super(software.amazon.jsii.JsiiObject.InitializationMode.Jsii); + software.amazon.jsii.JsiiEngine.getInstance().createNewObject(this); + } + + public software.amazon.jsii.tests.calculator.MutableObjectLiteral getMutableObject() { + return this.jsiiGet("mutableObject", software.amazon.jsii.tests.calculator.MutableObjectLiteral.class); + } + + public void setMutableObject(final software.amazon.jsii.tests.calculator.MutableObjectLiteral value) { + this.jsiiSet("mutableObject", java.util.Objects.requireNonNull(value, "mutableObject is required")); + } +} diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/MutableObjectLiteral.java b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/MutableObjectLiteral.java new file mode 100644 index 0000000000..bea2aafd41 --- /dev/null +++ b/packages/jsii-pacmak/test/expected.jsii-calc/java/src/main/java/software/amazon/jsii/tests/calculator/MutableObjectLiteral.java @@ -0,0 +1,72 @@ +package software.amazon.jsii.tests.calculator; + +@javax.annotation.Generated(value = "jsii-pacmak") +public interface MutableObjectLiteral extends software.amazon.jsii.JsiiSerializable { + java.lang.String getValue(); + void setValue(final java.lang.String value); + + /** + * @return a {@link Builder} of {@link MutableObjectLiteral} + */ + static Builder builder() { + return new Builder(); + } + + /** + * A builder for {@link MutableObjectLiteral} + */ + final class Builder { + private java.lang.String _value; + + /** + * Sets the value of Value + * @param value the value to be set + * @return {@code this} + */ + public Builder withValue(final java.lang.String value) { + this._value = java.util.Objects.requireNonNull(value, "value is required"); + return this; + } + + /** + * Builds the configured instance. + * @return a new instance of {@link MutableObjectLiteral} + * @throws NullPointerException if any required attribute was not provided + */ + public MutableObjectLiteral build() { + return new MutableObjectLiteral() { + private java.lang.String $value = java.util.Objects.requireNonNull(_value, "value is required"); + + @Override + public java.lang.String getValue() { + return this.$value; + } + + @Override + public void setValue(final java.lang.String value) { + this.$value = java.util.Objects.requireNonNull(value, "value is required"); + } + + }; + } + } + + /** + * A proxy class which represents a concrete javascript instance of this type. + */ + final static class Jsii$Proxy extends software.amazon.jsii.JsiiObject implements software.amazon.jsii.tests.calculator.MutableObjectLiteral { + protected Jsii$Proxy(final software.amazon.jsii.JsiiObject.InitializationMode mode) { + super(mode); + } + + @Override + public java.lang.String getValue() { + return this.jsiiGet("value", java.lang.String.class); + } + + @Override + public void setValue(final java.lang.String value) { + this.jsiiSet("value", java.util.Objects.requireNonNull(value, "value is required")); + } + } +} diff --git a/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst b/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst index 5e7176ac48..f7ad1c5810 100644 --- a/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst +++ b/packages/jsii-pacmak/test/expected.jsii-calc/sphinx/jsii-calc.rst @@ -973,6 +973,39 @@ CalculatorProps (interface) :type: number or ``undefined`` *(abstract)* +ClassWithMutableObjectLiteralProperty +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:class:: ClassWithMutableObjectLiteralProperty() + + **Language-specific names:** + + .. tabs:: + + .. code-tab:: c# + + using Amazon.JSII.Tests.CalculatorNamespace; + + .. code-tab:: java + + import software.amazon.jsii.tests.calculator.ClassWithMutableObjectLiteralProperty; + + .. code-tab:: javascript + + const { ClassWithMutableObjectLiteralProperty } = require('jsii-calc'); + + .. code-tab:: typescript + + import { ClassWithMutableObjectLiteralProperty } from 'jsii-calc'; + + + + + .. py:attribute:: mutableObject + + :type: :py:class:`~jsii-calc.MutableObjectLiteral`\ + + DefaultedConstructorArgument ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -2274,6 +2307,40 @@ Multiply :type: :py:class:`@scope/jsii-calc-lib.Value`\ *(readonly)* +MutableObjectLiteral (interface) +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +.. py:class:: MutableObjectLiteral + + **Language-specific names:** + + .. tabs:: + + .. code-tab:: c# + + using Amazon.JSII.Tests.CalculatorNamespace; + + .. code-tab:: java + + import software.amazon.jsii.tests.calculator.MutableObjectLiteral; + + .. code-tab:: javascript + + // MutableObjectLiteral is an interface + + .. code-tab:: typescript + + import { MutableObjectLiteral } from 'jsii-calc'; + + + + + + .. py:attribute:: value + + :type: string *(abstract)* + + Negate ^^^^^^ diff --git a/packages/jsii-runtime/package-lock.json b/packages/jsii-runtime/package-lock.json index 2ff60df500..1d06a2a3b4 100644 --- a/packages/jsii-runtime/package-lock.json +++ b/packages/jsii-runtime/package-lock.json @@ -44,6 +44,14 @@ "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" }, + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -73,6 +81,11 @@ "tweetnacl": "^0.14.3" } }, + "big.js": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz", + "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==" + }, "bind-obj-methods": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/bind-obj-methods/-/bind-obj-methods-2.0.0.tgz", @@ -198,6 +211,11 @@ "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" }, + "emojis-list": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz", + "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k=" + }, "escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", @@ -397,6 +415,11 @@ "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" }, + "json5": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz", + "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE=" + }, "jsprim": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", @@ -413,6 +436,21 @@ "resolved": "https://registry.npmjs.org/lcov-parse/-/lcov-parse-0.0.10.tgz", "integrity": "sha1-GwuP+ayceIklBYK3C3ExXZ2m2aM=" }, + "loader-utils": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.1.0.tgz", + "integrity": "sha1-yYrvSIvM7aL/teLeZG1qdUQp9c0=", + "requires": { + "big.js": "^3.1.3", + "emojis-list": "^2.0.0", + "json5": "^0.5.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, "log-driver": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/log-driver/-/log-driver-1.2.7.tgz", @@ -2943,6 +2981,15 @@ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==" }, + "source-map-loader": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/source-map-loader/-/source-map-loader-0.2.4.tgz", + "integrity": "sha512-OU6UJUty+i2JDpTItnizPrlpOIBLmQbWMuBg9q5bVtnHACqw1tn9nNwqJLbv0/00JjnJb/Ee5g5WS5vrRv7zIQ==", + "requires": { + "async": "^2.5.0", + "loader-utils": "^1.1.0" + } + }, "source-map-support": { "version": "0.5.9", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.9.tgz", diff --git a/packages/jsii-runtime/package.json b/packages/jsii-runtime/package.json index 7f5aefc78a..d4c78ad963 100644 --- a/packages/jsii-runtime/package.json +++ b/packages/jsii-runtime/package.json @@ -20,6 +20,7 @@ "jsii-build-tools": "^0.7.6", "jsii-calc": "^0.7.6", "nodeunit": "^0.11.3", + "source-map-loader": "^0.2.4", "typescript": "^3.0.1", "wasm-loader": "^1.3.0", "webpack": "^4.12.0", diff --git a/packages/jsii-runtime/webpack.config.js b/packages/jsii-runtime/webpack.config.js index d78c3f29cc..e808df74cc 100644 --- a/packages/jsii-runtime/webpack.config.js +++ b/packages/jsii-runtime/webpack.config.js @@ -6,7 +6,7 @@ module.exports = { path: __dirname + '/webpack', filename: 'jsii-runtime.js' }, - devtool: 'source-maps', + devtool: 'source-map', target: 'node', node: { console: false, @@ -16,5 +16,12 @@ module.exports = { __dirname: false, Buffer: false, setImmediate: false, + }, + module: { + rules: [{ + test: /\.js$/, + use: ['source-map-loader'], + enforce: 'pre' + }] } }