Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Parse and rewrite typescript files #5158

Closed
wants to merge 1 commit into from
Closed

Conversation

IlyasShabi
Copy link
Contributor

@IlyasShabi IlyasShabi commented Jan 27, 2025

What does this PR do?

This PR discusses different approaches to Node.js new Typescript support (--experimental-strip-types and --experimental-transform-types) and evaluates how they might impact our IAST module.
It specifically implements the first approach.

Overview

With Node.js introducing native type stripping via SWC, we have three possible approaches:

Approach 1: Use Module.stripTypeScriptTypes()

We directly invoke Module.stripTypeScriptTypes() to remove types from .ts files before passing the plain Javascript to our custom rewrite function.
The flags --experimental-strip-types or --experimental-transform-types will determine how Node.js transforms Typescript code.

Pros:
  • We rely on the officially supported Node.js workflow for Typescript, If they updates the internals we automatically benefit.
  • Minimal extra logic in our codebase
Cons:
  • First Node.js strips or transforms TS to JS, then we rewrite. This can be less efficient in performance.
  • If Node.js changes the function signature or behavior, we must adapt.

The approach described here is already implemented in this PR.

Approach 2: Use dd-native-iast-rewriter-js with configuration

Since Node.js's Amaro and our rewriter both use SWC under the hood, we can streamline the process by forwarding the flags directly to our rewriter as additional configuration options, enabling it to handle both TS and JS files while applying our instrumentation logic in a single pass, eliminating the need for separate type stripping and transformation steps.

Pros:
  • More efficient since we rewrite once
Cons:
  • We must stay in sync with new Node.js Typescript features or changes to SWC
  • Requires changes in both repositories
fn parse_js(
   source_file: &Arc<SourceFile>,
   handler: &Handler,
   compiler: &Compiler,
   config: &Config
) -> Result<Program> {

   let syntax = if config.is_ts_file {
       Syntax::Typescript(TsSyntax {
           tsx: false,
           decorators: true,
           dts: false,
           ..Default::default()
       })
   } else {
       Syntax::Es(EsSyntax {
           jsx: false,
           fn_bind: false,
           decorators: false,
           decorators_before_export: false,
           export_default_from: false,
           import_attributes: true,
           allow_super_outside_method: false,
           allow_return_outside_function: true,
           auto_accessors: true,
           ..Default::default()
       })
   };

   compiler.parse_js(
       source_file.to_owned(),
       handler,
       EsVersion::latest(),
       syntax,
       IsModule::Unknown,
       Some(&compiler.comments() as &dyn Comments),
   )
}

Approach 3: Use dd-native-iast-rewriter-js Typescript only

Similar to the 2nd approach, but we always parse files (even plain Javascript) under SWC’s Typescript syntax, then we only do the rewriting in one pass.

Pros:
  • We always use Syntax::Typescript, so no branching logic between JS/TS
  • Same performance benefit as 2nd approach? (Not sure if JS file parsing time can be impacted)
Cons:
  • We could have some Edge cases between JS/TS features
  • We still have to track TS + JS evolution to ensure correctness
fn parse_js(
    source_file: &Arc<SourceFile>,
    handler: &Handler,
    compiler: &Compiler,
) -> Result<Program> {
    let ts_syntax = TsSyntax {
        tsx: false,
        decorators: true,
        dts: false,
        ..Default::default()
    };

    compiler.parse_js(
        source_file.to_owned(),
        handler,
        EsVersion::latest(),
        Syntax::Typescript(ts_syntax),
        IsModule::Unknown,
        Some(&compiler.comments() as &dyn Comments),
    )
}

There are other potential suggestions, such as using Amaro in a manner similar to the first approach, though this requires installing an additional dependency that Node.js already provides.

Feel free to discuss each suggestion or propose new ones

Plugin Checklist

Additional Notes

Copy link

Overall package size

Self size: 8.53 MB
Deduped: 94.89 MB
No deduping: 95.41 MB

Dependency sizes | name | version | self size | total size | |------|---------|-----------|------------| | @datadog/libdatadog | 0.4.0 | 29.44 MB | 29.44 MB | | @datadog/native-appsec | 8.4.0 | 19.25 MB | 19.26 MB | | @datadog/native-iast-taint-tracking | 3.2.0 | 13.9 MB | 13.91 MB | | @datadog/pprof | 5.4.1 | 9.76 MB | 10.13 MB | | protobufjs | 7.2.5 | 2.77 MB | 5.16 MB | | @datadog/native-iast-rewriter | 2.6.1 | 2.59 MB | 2.73 MB | | @opentelemetry/core | 1.14.0 | 872.87 kB | 1.47 MB | | @datadog/native-metrics | 3.1.0 | 1.06 MB | 1.46 MB | | @opentelemetry/api | 1.8.0 | 1.21 MB | 1.21 MB | | import-in-the-middle | 1.11.2 | 112.74 kB | 826.22 kB | | source-map | 0.7.4 | 226 kB | 226 kB | | opentracing | 0.14.7 | 194.81 kB | 194.81 kB | | lru-cache | 7.18.3 | 133.92 kB | 133.92 kB | | pprof-format | 2.1.0 | 111.69 kB | 111.69 kB | | @datadog/sketches-js | 2.1.0 | 109.9 kB | 109.9 kB | | semver | 7.6.3 | 95.82 kB | 95.82 kB | | lodash.sortby | 4.7.0 | 75.76 kB | 75.76 kB | | ignore | 5.3.1 | 51.46 kB | 51.46 kB | | shell-quote | 1.8.1 | 44.96 kB | 44.96 kB | | istanbul-lib-coverage | 3.2.0 | 29.34 kB | 29.34 kB | | rfdc | 1.3.1 | 25.21 kB | 25.21 kB | | @isaacs/ttlcache | 1.4.1 | 25.2 kB | 25.2 kB | | tlhunter-sorted-set | 0.1.0 | 24.94 kB | 24.94 kB | | limiter | 1.1.5 | 23.17 kB | 23.17 kB | | dc-polyfill | 0.1.4 | 23.1 kB | 23.1 kB | | retry | 0.13.1 | 18.85 kB | 18.85 kB | | jest-docblock | 29.7.0 | 8.99 kB | 12.76 kB | | crypto-randomuuid | 1.0.0 | 11.18 kB | 11.18 kB | | ttl-set | 1.0.0 | 4.61 kB | 9.69 kB | | path-to-regexp | 0.1.12 | 6.6 kB | 6.6 kB | | koalas | 1.0.2 | 6.47 kB | 6.47 kB | | module-details-from-path | 1.0.3 | 4.47 kB | 4.47 kB |

🤖 This report was automatically generated by heaviest-objects-in-the-universe

@IlyasShabi IlyasShabi closed this Feb 11, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant