GithubHelp home page GithubHelp logo

aws / jsii Goto Github PK

View Code? Open in Web Editor NEW
2.6K 44.0 239.0 210.55 MB

jsii allows code in any language to naturally interact with JavaScript classes. It is the technology that enables the AWS Cloud Development Kit to deliver polyglot libraries from a single codebase!

Home Page: https://aws.github.io/jsii

License: Apache License 2.0

Shell 0.57% TypeScript 68.22% JavaScript 1.23% Java 7.22% C# 12.75% Python 3.35% Dockerfile 1.03% PowerShell 0.09% Smalltalk 0.01% F# 0.01% Go 5.41% Batchfile 0.01% CSS 0.12%
aws node cross-language typescript

jsii's People

Contributors

allcontributors[bot] avatar aws-cdk-automation avatar chriscbr avatar comcalvi avatar corymhall avatar costleya avatar dependabot-preview[bot] avatar dependabot[bot] avatar dstufft avatar eltociear avatar garnaat avatar iliapolo avatar kaizencc avatar madeline-k avatar mergify[bot] avatar mpiroc avatar mrarnoldpalmer avatar mrgrain avatar netanir avatar ngl321 avatar nija-at avatar njlynch avatar otaviomacedo avatar rix0rrr avatar romainmuller avatar shivlaks avatar skinny85 avatar somanyhs avatar sullis avatar yuth avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jsii's Issues

cannot webpack jsii-runtime since 'source-map' dynamically requires mappings.wasm

jsii-kernel uses [source-map][1] which depends on a web assembly module mappings.wasm. This is okay until we tried to bundle jsii-runtime into a single resource so it can be embedded into jsii native clients (to reduce external deps).

Since mappings.wasm is being dynamically loaded (using fs.readFile), webpack is unable to include it in the bundle.

Thread safety for languages that support multi-threading

It should be possible to interact with CDK classes across multiple threads. However, the jsii runtime is single threaded (uses blocking STDIO to interact with the host). This means that at the moment, if multiple threads attempt to interact with CDK classes, they will likely corrupt the runtime protocol.

At a minimum, we should issue an error if access from multiple threads is attempted

Generator cannot detect namespace conflicts when a sub-namespace is declared by an external type that isn't included in `externals`

In .NET, a fully-qualified type name must not collide with a fully-qualified namespace name. The generator attempts to detect these collisions (and rename the type to avoid them). To do this, it needs to know every possible namespace that could cause a conflict.

For root namespaces, this is simple: just inspect the targets property of the assembly itself as well as each of its dependencies (recursively). However, a type can also declare a sub-namespace by including the sub-namespace in its fqn. So we also search types and externals for any sub-namespaces.

The problem arises when a type in my-dependency declares a sub-namespace, but that type is not referenced from my-assembly (and therefore does not appear in externals). The generator has no way to be aware of this sub-namespace, so it can't detect conflicts.

When the generated .NET code for my-assembly is compiled, it takes a reference on my-dependency. So every namespace in my-dependency (even those not referenced from my-assembly) is available to the compiler, and can cause conflicts.

Previously this wasn't a problem, because all external types were present in dependencies. Now that we've switched to externals, this is no longer the case.

Improve stack traces across language boundaries

When making a cross-language call that ends up throwing an exception, the stack trace only contains the NodeJS section, and not the host application section. The same applies when a stack trace is internally gathered (for example, to track construct creation locations).

The runtime needs to pass a list of stack frames to the kernel so the exception stack trace can be enhanced to include all relevant information. The kernel then will need to somehow make this external trace a part of the regular trace, so that no special handling is required at stack trace collecting sites.

This could be done by runtime-generating one or more methods, just for the sake of adding stack frames in the Node process. It may also be possible to leverage the fact that almost any string can be a valid method name (so as to only use one stack frame instead of several).

Disambiguate the response types

Currently it's not possible to parse a response from the jsii-runtime into a typed structure without your parser knowing ahead of time what type it is expecting. It would be great if the jsii-runtime would include enough information in the response to know what type the response is, then a parser could parse it into a typed structure without relying on out of band information.

This could be as simple as just adding an extra key alongside the ok key, that included that information in it.

Kernel API: 'Complete' request uses different shapes for asynchronous and synchronous callbacks

@mpiroc wrote:

Jsii supports both synchronous and asynchronous overrides. The request to 'complete' an async callback looks like this:

{
    api: "complete",
    cbid: ...,
    error: ...,
    result: ...,
}

But the request to 'complete' a synchronous callback looks like this:

{
    complete: {
        cbid: ...,
        error: ...,
        result: ...,
    }
}

It would simplify backend implementations if synchronous callbacks had the same shape as synchronous callbacks.

Auto-detect breaking changes and enforce semver

Since jsii understands the API of a module, we can determine if there were breaking changes between two versions of the API. This is a very powerful capability and we should introduce it early in the game. This also ties nicely into the desire to review API changes via the normal code review process.

The low-level building block consists of a capability to compare two jsii specs and determine if the changes are minor or major based on the semver specification. The india library implements a similar approach based on these rules (maybe we can use india or extends it somehow to support jsii specs).

Now that we have the ability to compare two jsii specs, we should consider a mode for the compiler to automatically detect breaking changes. This will require checking-in the jsii spec of the module into source control and adding an option to fail the build in case breaking changes are introduced. The workflow (which is not flushed out yet) should also support enforcing version bumps based on the type of changes. See semantic-release - perhaps we can plug into it somehow so this will integarte with our release process.

Consider making the Hello message a response to a request

Currently with the jsii-runtime, whenever the runtime is started it emits a HelloResponse message. This makes sense to ensure that the runtime version is compatible with the client. However, the way it is currently implemented means that the protocol layer (either implicit or explicit) has to specially handle this message.

The typical flow when interacting with the jsii-runtime is essentially a request/response cycle, for every response you get you had to first make a request. However, the hello message is different, it is a response without a correlating request, which means that the protocol layer has to handle a request-less response for just this one single message.

It seems like it'd be sane to instead make it just another command that can be invoked. So instead you'd end up doing something like:

> {"api": "hello"}
< {"hello": "[email protected]"}

We could mimic the command structure even more, and move the {"hello": "..."} into a {"ok": {"hello": "..."}} structure.

This would allow clients to treat every interaction with the jsii-runtime as a request/response cycle, eliminating the need to special case the protocol. Besides the obvious compatibility issues, the biggest issue I see with this is that because this is required to be stable, if we change the framing or format in some way, this command would have to be excluded from that, so you'd end up special casing the parsing of the response for this command instead.

Because of the nature of this command, it would have to be stable for basically forever, but the rest of the protocol can evolve as required.

This would also allow some minor amount of startup optimization for implementations that bundle a jsii-runtime, because the bundling will prevent version drift that this seeks to eliminate.

Thoughts?

Multi-language build

At the moment, the jsii toolchain covers the process until a generated code package in all supported programming languages. This leaves the actual build to users, which is unneeded since this is boilerplate that needs to be implemented by all users.

The toolchains required for all languages is expected to be installed on your system (and we will create a docker image that contains all of them).

A few other things to consider:

  1. What is the post-build publishing story? Perhaps this is actually part of the "packaging" stage.
  2. We need to also make sure that the development environment for contributors doesn't require the entire toolchain because that will become a barrier for contributors. Perhaps the actual multi-language build will only happen during "pack" and contributors can just utilize our build servers to do that for them instead of having to install the entire toolchain.
  3. It should be possible to also deprecate a package across all package managers.

Inject runtime type checks via jsii compilation

Consider modifying the jsii compiler to inject runtime type checking into the emitted javascript code.
We should consider using ts-runtime by fabiandev (based on his MA thesis).

We can verify everything based on the jsii type info that's bundled within the module:

  1. Names of types
  2. Names of methods/properties
  3. Number of arguments
  4. Types of arguments
  5. Existence and types of object properties
  6. Return types

https://dev.doctorevidence.com/how-to-write-a-typescript-transform-plugin-fc5308fdd943

Rename lambda.Lambda to lambda.Function

Since we now encourage using namespaced imports import lambda = require('@aws-cdk/aws-lambda'), it should be fine (at least from JavaScript's perspective) to use Function as the name of the class. If this proves problematic in other languages, jsii generators should mangle the name (similarly to other reserved words).

Also, clean up the class names in @aws-cdk/aws-lambda not to include a Lambda prefix

Bundle node.js into client libraries

Ideally we’d like the various language-specific runtime libraries to be self contained and not require node.js installed on the system. This means that we should bundle node.js itself with the libraries for all target platforms, and choose the right one when starting the jsii-runtime.

We can use something like nexe to bundle the runtime and node together, instead of separately.

Unable to return Promise<void>

While methods are fine to return void, they cannot return a Promise<void>, as JSII interprets this as Promise<unknown type>.

Reproduction:

export class PromiseOfVoid {
  async function returnsVoidPromise(): Promise<void> {
    return;
  }
}

jsii-java: arrays are mutable but won’t affect JavaScript code

At the moment, an array property is implemented as a List in java. This gives the impression that you could do something like obj.getProperty() and then modify the list. But in reality, this is not a mutable property. The TypeScript behavior is mutable (e.g. obj.Property.push(x). This means that the "correct" approach would be to implement class that derives from List and will affect the underlying javascript array.

Unable to represent Error/Exception types

Subclasses of Error cannot be exported by a JSII module, since Error is not a JSII class.

Repro:

export class CustomError extends Error {
  constructor(message: string) {
    super(message);
  }
}

Copy jsdocs from base members

We should make sure jsii automatically copies jsdocs if a class has a member that overrides a member in one of the base classes and doesn't have docs.

Consider injecting runtime type-checks to .js when compiling jsii modules

The TypeScript compiler will warn if there is a type mismatch, but we don't get this benefit in runtime. This has a few implications:

  1. For javascript (not typescript) users.
  2. For users of other dynamic languages.

Ideally, if we could find a way to automatically inject runtime type checks to methods, that would be awesome. Otherwise, we will need more rigour around surface area type checks.

Here's a library that does exactly that: https://github.com/fabiandev/ts-runtime

Dependency collisions (co-existence of multiple versions of the same assembly)

Various host languages have varying degrees of support for co-existence of multiple versions of the same module within their runtime closure. For example, node/npm simply allows that (since the runtime closure is a directory tree), Java supports it only with certain class loaders, etc.

The questions are:

  1. Should the jsii-runtime support it (at the moment, it intentionally blocks this from happening)
  2. What happens in environments where this is not supported? Do we have a way to help users resolve these conflicts?

ERROR: Cannot write file '.../lib/index.d.ts' because it would overwrite input file.

We're still doing something wrong in configuring our package build.

When I run tsc in a directory, it borks with this error. It doesn't when I run jsii, but that's because JSII has its own source discovery mechanism which is distinct from what tsc would do.

This is probably because our package.json:"types" entry points to a .d.ts file, instead of the source .ts file.

If we want to do a TypeScript -> JavaScript+Type Annotations build, we should probably do it out-of-source and rewrite the package.json before publishing.

Rely ARGV to jsii kernel upon initialization

To allow jsii code to read ARGV from process.argv, during the initial kernel handshake, the host process' ARGV should be passed and the kernel should mutate the sandbox's argv to match.

"cdk diff" does not show old and new values when a property changes

Repro: in Getting Started, follow the guide until you reach the "cdk diff" stage.

The output is expected to be:

[~] πŸ›  Updating MyQueueE6CA6235 (type: AWS::SQS::Queue)
 └─ [~] .VisibilityTimeout:
    └─ Old value: 300
    └─ New value: 500

But the output is:

[~] πŸ›  Updating MyQueueE6CA6235 (type: AWS::SQS::Queue)
 └─ [~] .VisibilityTimeout:

Add naming convention enforcement to jsii

jsii should provide a predictable style of surface area for many programming languages with multiple styles. It will be beneficial to enforce a convention for naming at the jsii layer, so language-specific generators will be able to rely on that convention to generate idiomatic conventional surface area for their language.

I think jsii should enforce the JavaScript conventions:

  • Class names: pascal case
  • Properties: camel case
  • Methods: camel case
  • Arguments: camel case
  • Consts: all caps

Java "step" builders are not future-compatible

Brought up by @kiiadi - our beautiful Java "step" builder, which enforces required fields before optional fields will cause backwards compatibility issues when a field is changed from required to optional (which is not supposed to be a breaking change).

Furthermore, the current approach will also cause a breaking change if the order of properties change across revisions, which is also unacceptable.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.