effector / swc-plugin-legacy

SWC plugin to efficiently work with effector
https://npmjs.com/@effector/swc-plugin
27 stars 3 forks source link

Doesn't work with nextjs 13.1 #19

Open timofei-iatsenko opened 1 year ago

timofei-iatsenko commented 1 year ago
/**
 * @type {import('next').NextConfig}
 */
const config = {
  reactStrictMode: true,
  experimental: {
    swcPlugins: [
      ['@effector/swc-plugin', {}],
    ],
  },
}
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: LayoutError', /Users/k.mironov/.cargo/registry/src/github.com-1ecc6299db9ec823/rkyv-0.7.37/src/impls/core/mod.rs:265:36
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at 'thread 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/node_modules/next/dist/client/router.js")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: out of bounds memory access
    2: heap_get_oob', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/node_modules/next/dist/client/router.js")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: call stack exhausted
    2: stk_ovf', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/node_modules/next/dist/client/dev/amp-dev.js")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: call stack exhausted
    2: stk_ovf', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/node_modules/next/dist/client/next-dev.js")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: out of bounds memory access
    2: heap_get_oob', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: LayoutError', /Users/k.mironov/.cargo/registry/src/github.com-1ecc6299db9ec823/rkyv-0.7.37/src/impls/core/mod.rs:265:36
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/projects/client-react/pages/_app.page.tsx")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: call stack exhausted
    2: stk_ovf', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: LayoutError', /Users/k.mironov/.cargo/registry/src/github.com-1ecc6299db9ec823/rkyv-0.7.37/src/impls/core/mod.rs:265:36
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/node_modules/next/dist/pages/_error.js")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: call stack exhausted
    2: stk_ovf', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
thread '<unnamed>' panicked at 'called `Result::unwrap()` on an `Err` value: LayoutError', /Users/k.mironov/.cargo/registry/src/github.com-1ecc6299db9ec823/rkyv-0.7.37/src/impls/core/mod.rs:265:36
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/projects/client-react/pages/_document.page.tsx")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: call stack exhausted
    2: stk_ovf', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/projects/client-react/sentry.server.config.js")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: out of bounds memory access
    2: heap_get_oob', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/projects/client-react/pages/_app.page.tsx")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: out of bounds memory access
    2: heap_get_oob', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.236.14/src/plugin.rs:228:14
thread '<unnamed>' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/node_modules/next/dist/pages/_error.js")'

Caused by:
    0: failed to invoke `/Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm` as js transform plugin at /Users/tim/projects/timescenery/node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
    1: RuntimeError: out of bounds memory access

It's probably caused by a version mismatch between SWC version used in nextjs and SWC crates this plugin build with. Probably bumping to

swc_core = { version = "0.52.8", features = [".."] }

Should help

vvysokiy commented 1 year ago

Adding from the example from https://github.com/effector/swc-plugin/issues/18 Example https://github.com/vvysokiy/swc-jest-decorators/tree/issue-19

"@effector/swc-plugin": "0.0.8",
"@swc/core": "^1.3.26",
"@swc/helpers": "^0.4.14",
"@swc/jest": "^0.2.24",

Simple test

describe('describe', () => {
  test('test', () => {
    expect(1).toEqual(1);
  })
});

Error

 FAIL  tests/test.spec.tsers/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc-0.241.5/src/plugin.rs:228:14
  ● Test suite failed to run

    failed to handle: failed to invoke plugin: failed to invoke plugin on 'Some("/Users/vladimirvysokij/Documents/projects/swc-jest-decorators/tests/test.spec.ts")'

    Caused by:
        0: failed to invoke `@effector/swc-plugin` as js transform plugin at node_modules/@effector/swc-plugin/target/wasm32-wasi/release/effector_swc_plugin.wasm
        1: RuntimeError: out of bounds memory access
        2: heap_get_oob

It seems v0.0.8 breaks the compilation

timofei-iatsenko commented 1 year ago

I tried to recompile a lib locally with newer versions of SWC deps. That didn't help. But I didn't manage to build it with Rust stable channel because one of the deps (not a swc failed). So i installed latest nightly, and don't know now it panics because of nightly rust or because of deps mismatch.

vvysokiy commented 1 year ago

I tried to recompile a lib locally with newer versions of SWC deps. That didn't help. But I didn't manage to build it with Rust stable channel because one of the deps (not a swc failed). So i installed latest nightly, and don't know now it panics because of nightly rust or because of deps mismatch.

Check "@effector/swc-plugin": "0.0.7" for your build

timofei-iatsenko commented 1 year ago

With 0.0.7 I receive another error, now from plugins sources:

thread '' panicked at 'called Option::unwrap() on a None valuethread '', src/effector.rs' panicked at ':called Option::unwrap() on a None value252:9 note: run with RUST_BACKTRACE=1 environment variable to display a backtrace ', src/effector.rs:252:9 note: run with RUST_BACKTRACE=1 environment variable to display a backtrace thread 'thread '' panicked at '' panicked at 'failed to invoke plugin: failed to invoke plugin on 'Some("/Users/tim/projects/timescenery/projects/client-react/infrastructure/effector/app/router-domain.ts")'

timofei-iatsenko commented 1 year ago

Related and might be interesting to others https://github.com/swc-project/swc/issues/6807

Drevoed commented 1 year ago

Should be fixed by #26.

Can you please try it out?

timofei-iatsenko commented 1 year ago

The error changed, now it's

thread '' panicked at 'position 0 does not resolve to a source location', /Users/runner/.cargo/registry/src/github.com-1ecc6299db9ec823/swc_common-0.29.19/src/source_map.rs:1086:17

I will try to isolate broken code later one and post it here.

timofei-iatsenko commented 1 year ago

I've found a root cause. This happens only when @effector/swc-plugin goes after other plugins in swcrc. If i change the order and make effector plugin goes first - no error.

Do the effector plugin somehow directly consume or manipulate sourcemaps?

PS i'm the author of @lingui/swc-plugin and I know that there are no direct source map manipulations and all spans provided correctly (DUMMY_SPAN for new nodes and existing spans for transformed nodes), so sourcemaps after this plugin should be correct if no error in the swc itself.

.swcrc

{
  "$schema": "https://json.schemastore.org/swcrc",
  "jsc": {
    "parser": {
      "syntax": "typescript",
      "tsx": true
    },
    "transform": {
      "react": {
        "runtime": "automatic",
        "importSource": "@emotion/react"
      }
    },
    "target": "es2020",
    "loose": false,
    "externalHelpers": false,
    "keepClassNames": false,
    "experimental": {
      "plugins": [
        ["@lingui/swc-plugin", {}],
        ["@effector/swc-plugin", {}],
      ]
    }
  },
  "minify": false
}
npx swc ./component.tsx -d dist-swc --config-file="./.swcrc"
// component.tsx
import Script from 'next/script';
import { ConsentManager } from '@segment/consent-manager';
import { Trans, t } from '@lingui/macro';
import { PreferenceDialogTemplate } from '@segment/consent-manager/types/types';
import { css } from '@emotion/react';
import { zIndex } from '@/styles/z-index';

type Props = {
  segmentKey: string;
  isEnabled: boolean;
  bannerAsModal: boolean;
};

const bannerCss = css`
  position: fixed;
  bottom: 0;
  z-index: ${zIndex.segment};
  width: 100%;
  display: block;
`;

export const SegmentSnippet = (props: Props) => {
  const template: PreferenceDialogTemplate = {
    headings: {
      allowValue: t`Allow`,
      categoryValue: t`Category`,
      purposeValue: t`Purpose`,
      toolsValue: t`Tools`,
    },
    checkboxes: {
      noValue: t`No`,
      yesValue: t`Yes`,
    },
    actionButtons: {
      cancelValue: t`Cancel`,
      saveValue: t`Save`,
    },
    cancelDialogButtons: {
      cancelValue: t`Yes, Cancel`,
      backValue: t`Go Back`,
    },
    categories: [
      {
        key: 'functional',
        name: t`Functional`,
        description:
          t`To monitor the performance of our site and to enhance your browsing experience.`,
        example: t`For example, these tools enable you to communicate with us via live chat.`,
      },
      {
        key: 'marketing',
        name: t`Marketing and Analytics`,
        description:
          t`To understand user behavior in order to provide you with a more relevant browsing experience or personalize the content on our site.`,
        example:
          t`For example, we collect information about which pages you visit to help us present more relevant information.`,
      },
      {
        key: 'advertising',
        name: t`Advertising`,
        description:
          t`To personalize and measure the effectiveness of advertising on our site and other websites.`,
        example:
          t`For example, we may serve you a personalized ad based on the pages you visit on our site.`,
      },
      {
        key: 'essential',
        name: t`Essential`,
        description: t`We use browser cookies that are necessary for the site to work as intended.`,
        example:
          t`For example, we store your website data collection preferences so we can honor them if you return to our site. You can disable these cookies in your browser settings but if you do the site may not work as intended.`,
      },
    ],
  };

  const bannerContent = (
    <span>
      <Trans>
        We use cookies (and other similar technologies) to collect data to improve your experience on
        our site. By using our website, you’re agreeing to the collection of data as described in our{' '}
        <a href="https://road.travel/welcome/en/privacy/" rel="noreferrer" target="_blank">
          Website Data Collection Policy
        </a>
        .
      </Trans>
    </span>
  );
  const bannerSubContent = t`You can change your preferences at any time.`;
  const preferencesDialogTitle = t`Data Collection Settings`;
  const preferencesDialogContent =
    t`We use data collected by cookies and JavaScript libraries to improve your browsing experience, analyze site traffic, deliver personalized advertisements, and increase the overall performance of our site.`;
  const cancelDialogTitle = t`Are you sure you want to cancel?`;
  const cancelDialogContent =
    t`Your preferences have not been saved. By continuing to use our website, you՚re agreeing to our Website Data Collection Policy.`;

  return (
    <>
      <Script
        id="show-banner"
        dangerouslySetInnerHTML={{
          __html: `!function(){var analytics=window.analytics=window.analytics||[];if(!analytics.initialize)if(analytics.invoked)window.console&&console.error&&console.error("Segment snippet included twice.");else{analytics.invoked=!0;analytics.methods=["trackSubmit","trackClick","trackLink","trackForm","pageview","identify","reset","group","track","ready","alias","debug","page","once","off","on","addSourceMiddleware","addIntegrationMiddleware","setAnonymousId","addDestinationMiddleware"];analytics.factory=function(e){return function(){var t=Array.prototype.slice.call(arguments);t.unshift(e);analytics.push(t);return analytics}};for(var e=0;e<analytics.methods.length;e++){var key=analytics.methods[e];analytics[key]=analytics.factory(key)}analytics.load=function(key,e){var t=document.createElement("script");t.type="text/javascript";t.async=!0;t.src="https://cdn.segment.com/analytics.js/v1/" + key + "/analytics.min.js";var n=document.getElementsByTagName("script")[0];n.parentNode.insertBefore(t,n);analytics._loadOptions=e};;analytics.SNIPPET_VERSION="4.13.2";
          analytics.page();
          }}();`,
        }}
      />

      <div css={bannerCss}>
        <ConsentManager
          writeKey={props.segmentKey}
          bannerContent={bannerContent}
          bannerSubContent={bannerSubContent}
          bannerAsModal={props.bannerAsModal}
          preferencesDialogTitle={preferencesDialogTitle}
          preferencesDialogContent={preferencesDialogContent}
          cancelDialogTitle={cancelDialogTitle}
          cancelDialogContent={cancelDialogContent}
          bannerActionsBlock={true}
          preferencesDialogTemplate={template}
          shouldRequireConsent={() => props.isEnabled}
          bannerHideCloseButton={true}
        />
      </div>
    </>
  );
};

As you see there are no calls to effector in this file, but plugin still trying to apply some logic.

timofei-iatsenko commented 1 year ago

@Drevoed It seems you need to check for is_dummy() before trying to map a position

if ident.span.lo.is_dummy() {
 let loc = self.cm.lookup_char_pos(ident.span.lo);
 self.state.loc = Some(loc);
}

Because position 0 mentioned in the message position 0 does not resolve to a source location is actually a dummy position:

// .cargo/registry/src/github.com-1ecc6299db9ec823/swc_common-0.29.27/src/syntax_pos.rs
impl BytePos {
// ...
    /// Returns true if this is synthesized and has no relevant input source
    /// code.
    pub const fn is_dummy(self) -> bool {
        self.0 == 0
    }
}

Here is possible the same root cause of issue: https://github.com/effector/swc-plugin/issues/18#issuecomment-1403178140