fgnass / domino

Server-side DOM implementation based on Mozilla's dom.js
BSD 2-Clause "Simplified" License
768 stars 120 forks source link

SyntaxError: strict mode code may not contain 'with' statements #153

Open RedactedProfile opened 4 years ago

RedactedProfile commented 4 years ago

This error comes to me via usage of Angular Universal. When attempting to serve my development server and accessing any of the pages, I am greeted to a blank screen and this error in the console:

SyntaxError: strict mode code may not contain 'with' statements

specifically pointing to this line as the issue: https://github.com/fgnass/domino/blob/master/lib/sloppy.js#L10

Honestly I'm not quite sure how to proceed, this is my first time using any of this stuff, but because this file's been around since 2015 unchanged, I imagine the browsers have just recently started getting picky about it?

spencerfontein commented 4 years ago

I am having the same issue

cscott commented 4 years ago

It is most likely a change in how Angular is bundling domino; as the comment in that file indicates, it is deliberately not in strict mode. Angular apparently is enabling strict mode for every domino file.

spencerfontein commented 4 years ago

@cscott thanks for the reply. Any chance you know how to tell angular to not bundle this in strict mode? Or make a change to this package to not use with?

Or any other ideas you may have.

Dartaw commented 4 years ago

Having this issue as well.

BeejeeDS commented 4 years ago

Having the same problem

cscott commented 4 years ago

What's the bug # on the angularjs project? This is not a domino bug, so commenting here isn't being seen by anyone who knows angular well enough to fix the underlying issue.

RedactedProfile commented 4 years ago

What's the bug # on the angularjs project? This is not a domino bug, so commenting here isn't being seen by anyone who knows angular well enough to fix the underlying issue.

I think that's the bigger issue here, is that while this may not be "strictly" an issue with Domino, and can be fixed by a higher package int he chain, but which one is it? Webpack? Angular CLI? Which dependency is it even that uses Domino? Is it a sub sub sub child of higher package? Because for 99.99999999% of everything else, those are fine.

But at the bottom of the chain here, is Domino's usage of a practice that is not recommended: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/with

So while it sucks that webpack or whatever is accidentally carrying over a use strict into what is supposed to be a not-strict file (because there is no use sloppy), and I get it that that is clearly stated in the comments of the source file causing the issue, the other half here is that maybe this file should be updated to use a stricter standard anyways, or else packages relying on this dependency might want to look elsewhere and no one wants that.

The bigger problem is with packagers like webpack and gulp concatting 3rd party source code into a single source. Using sloppy mode is going to naturally cause problems when anything packaged as a higher priority above it slaps a use strict in there, which is going to be an overwhelming amount of the time (and there is no way to just "turn off" strict mode by stating a use sloppy somewhere)

--

I'm not trying to come off as harshly critical and I'm not even trying to tell you what to do or how to handle your project, I'm purely coming at this as a developer who installed a default version of a project that wouldn't function because a single file way down the dependency chain wasn't using strict mode and using non-strict compatible functionality and ends up bj0rking the whole thing because of it.

The question is for Webpack or Angular CLI, what CAN they do about it? Probably nothing. ngUniversal with Express however can probably figure out which dependency they need to update that doesn't end up using Domino however, and just me personally I find that as well undesirable. Domino is clearly good at what it does. But this issue can be fixed at this level, whether it is or never does is entirely up to it's collaborators, and that's totally fair.

I just wanted to present my case and inform of why this is a problem now, will likely continue to be a problem going forward, and why you might want to look into making this file comply to stricter ECMA standards for maximum compatibility image

On the same token, I empathize with the idea of "it's not really our problem either" and that's definitely well within your stance to take.

I just hope that maybe it isn't is all and maybe a greater good can come out of this.

cscott commented 4 years ago

Well, you could start by opening a bug on the angular project, as I've recommended. It doesn't seem you've done that yet.

RedactedProfile commented 4 years ago

Well, you could start by opening a bug on the angular project, as I've recommended. It doesn't seem you've done that yet.

I truly do not believe Angular or even Angular CLI to be the issue here. I feel if it is to be escalated to a higher level package, it's likely Webpack or ngUniversal. To which, yeah, i'll open up an issue on ngUniversal next before Webpack. But I haven't because I still believe this problem can be dealt with here, to resolve any further problems down the road when and if domino is included in similar toolchains

BeejeeDS commented 4 years ago

Well, you could start by opening a bug on the angular project, as I've recommended. It doesn't seem you've done that yet.

I truly do not believe Angular or even Angular CLI to be the issue here. I feel if it is to be escalated to a higher level package, it's likely Webpack or ngUniversal. To which, yeah, i'll open up an issue on ngUniversal next before Webpack. But I haven't because I still believe this problem can be dealt with here, to resolve any further problems down the road when and if domino is included in similar toolchains

I've solved the problem by removing al the server side rendering code from my angular project. Including the reference to @angular/platform-server. My main.ts also had a reference to it. The package has a dependency to domino. Everything works like a charm now. I've already done this with success in 3 projects.

mjankucic-itk commented 4 years ago

Same issue here. Platform server from universal has dependency to domino. It’s not option to remove ssr code from angular project...

technolion commented 4 years ago

Same issue here. After Upgrading from Angular 8.2 to 9.0 domino can not be used any longer. Please fix.

gkalpak commented 4 years ago

For anyone landing on this thread: This seems to be an issue with how the dotnet command scaffolds the Angular project (and likely the fact that it uses a very outdated Angular CLI version). See the discussion in angular/angular#34970 for details.

Garudkar-Dnyaneshwar commented 4 years ago

Well, you could start by opening a bug on the angular project, as I've recommended. It doesn't seem you've done that yet.

I truly do not believe Angular or even Angular CLI to be the issue here. I feel if it is to be escalated to a higher level package, it's likely Webpack or ngUniversal. To which, yeah, i'll open up an issue on ngUniversal next before Webpack. But I haven't because I still believe this problem can be dealt with here, to resolve any further problems down the road when and if domino is included in similar toolchains

I've solved the problem by removing al the server side rendering code from my angular project. Including the reference to @angular/platform-server. My main.ts also had a reference to it. The package has a dependency to domino. Everything works like a charm now. I've already done this with success in 3 projects.

but i need ssr too then what is the solution? thanks

Trackerchum commented 3 years ago

I'm getting the same issue in a react project with custom webpack configuration, it appears to be babel that's causing it to throw the error. Strangely enough it's only throwing the error in Windows though.

Is this still being looked into at all? We need SSR

azuxx commented 3 years ago

Same problem here, I need SSR working properly. I have this error Uncaught SyntaxError: Strict mode code may not include a with statement vendor.js:172512. If I dive into this I got: Screenshot 2021-01-29 at 11 17 29

Plus, all (click) events in my templates got dead, why?

I upgraded properly Angular app from version 9, to version 10, and then version 11. Then I configured Angular Universal for ssr here: https://angular.io/guide/universal Then I configured successfully Ngx-translate to get it working with ssr here: https://andremonteiro.pt/ngx-translate-angular-universal-ssr/#:~:text=NGX%2DTranslate%20is%20an%20internationalization,and%20switch%20between%20them%20easily.

I don't have clue how to fix the (click) dead thing or if 'Strict mode code may not include a with statement vendor.js:172512' is related, how to remove that.

Any idea here? Thanks

bsumter commented 3 years ago

@azuxx, make sure you're importing BrowserTransferStateModule on the Browser Module (AppModule.ts), instead of the ServerTransferStateModule

azuxx commented 3 years ago

BrowserTransferStateModule

ServerTransferStateModule,
    BrowserTransferStateModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateServerLoaderFactory,
        deps: [TransferState]
      }
    }),

I tried to add BrowserTransferStateModule and keep ServerTransferStateModule because otherwise translations does not work. But, click events are still 'dead'.

Anyhow, we kept Angular App client rendered and we found to enable pre-rendering feature in Netfliy. I don't know if this will let me achieve the same results of server rendering but time is up😅

Thanks anyway @bsumter !

bsumter commented 3 years ago

Try to avoid loading server modules in the browser module.

app.module.ts imports:

BrowserModule.withServerTransition({ appId: 'serverApp' }),
HttpClientModule,
TransferHttpCacheModule,
BrowserTransferStateModule,
AppRoutingModule,
TranslateModule.forRoot({
  loader: {
    provide: TranslateLoader,
    useFactory: TranslateBrowserLoaderFactory,
    deps: [HttpClient, TransferState]
  },
}),

app.server.module.ts imports:

AppModule,
ServerModule,
ServerTransferStateModule,
TranslateModule.forRoot({
  loader: {
    provide: TranslateLoader,
    useFactory: TranslateServerLoaderFactory,
    deps: [HttpClient, TransferState]
  }
})
azuxx commented 3 years ago

Try to avoid loading server modules in the browser module.

app.module.ts imports:

BrowserModule.withServerTransition({ appId: 'serverApp' }),
HttpClientModule,
TransferHttpCacheModule,
BrowserTransferStateModule,
AppRoutingModule,
TranslateModule.forRoot({
  loader: {
    provide: TranslateLoader,
    useFactory: TranslateBrowserLoaderFactory,
    deps: [HttpClient, TransferState]
  },
}),

app.server.module.ts imports:

AppModule,
ServerModule,
ServerTransferStateModule,
TranslateModule.forRoot({
  loader: {
    provide: TranslateLoader,
    useFactory: TranslateServerLoaderFactory,
    deps: [HttpClient, TransferState]
  }
})

Thank you @bmeurer , I tried your suggestion but it did not work :(

Screenshot 2021-02-08 at 15 24 06

app.module

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    ForgotPasswordComponent,
    UserConfirmedComponent,
    SupportComponent,
    PrivacyPolicyComponent,
    TermsAndConditionsComponent
  ],
  imports: [
    BrowserModule.withServerTransition({appId: 'serverApp'}),
    AppRoutingModule,
    // ngx-translate and the loader module
    HttpClientModule,
    TransferHttpCacheModule,
    BrowserTransferStateModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateServerLoaderFactory,
        deps: [TransferState]
      }
    }),
    CoreModule,
    FormsModule,
    CommonModule,
    PdfViewerModule
  ],
  providers: [
    {provide: LOCALE_ID, useValue: 'it'},

  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

app.server.module

@NgModule({
  imports: [
    AppModule,
    ServerModule,
    ServerModule,
    ServerTransferStateModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateServerLoaderFactory,
        deps: [TransferState]
      }
    }),
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule {}
bsumter commented 3 years ago

@azuxx

You shouldn't be using translateServerLoaderFactory in app.module. Use TranslateBrowserLoaderFactory instead.

azuxx commented 3 years ago

@azuxx

You shouldn't be using translateServerLoaderFactory in app.module. Use TranslateBrowserLoaderFactory instead.

it worked! I did also other fixings and here we are 🚀

app.server.module

@NgModule({
  imports: [
    AppModule,
    ServerModule,
    ServerTransferStateModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateServerLoaderFactory,
        deps: [TransferState]
      }
    }),
  ],
  bootstrap: [AppComponent],
})
export class AppServerModule {
}

app.module.ts

registerLocaleData(localeIt, 'it');

@NgModule({
  declarations: [
    AppComponent,
    HomeComponent,
    ForgotPasswordComponent,
    UserConfirmedComponent,
    SupportComponent,
    PrivacyPolicyComponent,
    TermsAndConditionsComponent
  ],
  imports: [
    BrowserModule.withServerTransition({appId: 'serverApp'}),
    TransferHttpCacheModule,
    // ngx-translate and the loader module
    HttpClientModule,
    TranslateModule.forRoot({
      loader: {
        provide: TranslateLoader,
        useFactory: translateBrowserLoaderFactory,
        deps: [HttpClient, TransferState]
      }
    }),
    AppRoutingModule,
    CoreModule,
    FormsModule,
    CommonModule,
    PdfViewerModule
  ],
  providers: [
    {provide: LOCALE_ID, useValue: 'it'}
  ],
  bootstrap: [AppComponent]
})
export class AppModule {
}

Thank you! Have a good one @bsumter

NfNitLoop commented 3 years ago

This causes domino, and things that depend on it (ex: turndown), to not work correctly in skypack.

See: https://cdn.skypack.dev/error/build:domino@v2.1.6-RPQ3pQwxyHY1PYvBqErp

martinsotirov commented 2 years ago

Try to avoid loading server modules in the browser module.

This was it for me. I had imported FlexLayoutServerModule in app.module.ts instead of app.server.module.ts.

benjaminbekes commented 2 years ago

This error comes to me via usage of Angular Universal. When attempting to serve my development server and accessing any of the pages, I am greeted to a blank screen and this error in the console:

SyntaxError: strict mode code may not contain 'with' statements

specifically pointing to this line as the issue: https://github.com/fgnass/domino/blob/master/lib/sloppy.js#L10

Honestly I'm not quite sure how to proceed, this is my first time using any of this stuff, but because this file's been around since 2015 unchanged, I imagine the browsers have just recently started getting picky about it?

This error has occurred again in Angular 14+

There's no useful and applicable way of all things mentioned above for version 14.

I'm facing the same issue with the f*ing 'with' statement in domino. Getting error in a browser:

Uncaught SyntaxError: Strict mode code may not include a with statement (at ${sourceUrl}`;:40235:5)

which points to the place of:

/***/ 9226:
/*!*******************************************!*\
  !*** ./node_modules/domino/lib/sloppy.js ***!
  \*******************************************/
/***/ ((module) => {

/* Domino uses sloppy-mode features (in particular, `with`) for a few
 * minor things.  This file encapsulates all the sloppiness; every
 * other module should be strict. */

/* jshint strict: false */

/* jshint evil: true */

/* jshint -W085 */
module.exports = {
  Window_run: function _run(code, file) {
    if (file) code += '\n//@ sourceURL=' + file;
    with (this) eval(code); // <-------------------------------------- POINTING HERE ------------
  },
  EventHandlerBuilder_build: function build() {
    try {
      with (this.document.defaultView || Object.create(null)) with (this.document) with (this.form) with (this.element) return eval("(function(event){" + this.body + "})");
    } catch (err) {
      return function () {
        throw err;
      };
    }
  }
};

I've lost 3 days solving that stupid error, searching over the internet, and going over all similar issues that are not applicable to Angular 14. I'm stuck in the SSR development, even my click events as it was mentioned above don't work at all. Any updates to this issue? Thanks.

package.json

{
  "name": "landing-page",
  "version": "0.0.0",
  "scripts": {
    "ng": "ng",
    "start": "ng serve",
    "build": "ng build",
    "watch": "ng build --watch --configuration development",
    "test": "ng test",
    "dev:ssr": "ng run landing-page:serve-ssr",
    "serve:ssr": "node dist/landing-page/server/main.js",
    "build:ssr": "ng build && ng run landing-page:server",
    "prerender": "ng run landing-page:prerender"
  },
  "private": true,
  "dependencies": {
    "@angular/animations": "^14.2.0",
    "@angular/common": "^14.2.0",
    "@angular/compiler": "^14.2.0",
    "@angular/core": "^14.2.0",
    "@angular/forms": "^14.2.0",
    "@angular/platform-browser": "^14.2.0",
    "@angular/platform-browser-dynamic": "^14.2.0",
    "@angular/platform-server": "^14.2.0",
    "@angular/router": "^14.2.0",
    "@fortawesome/fontawesome-free": "^6.1.1",
    "@nguniversal/express-engine": "^14.1.0",
    "@types/aos": "^3.0.4",
    "aos": "^2.3.4",
    "primeflex": "^2.0.0",
    "primeng": "^14.0.2",
    "express": "^4.15.2",
    "rxjs": "~7.4.0",
    "tslib": "^2.3.0",
    "zone.js": "~0.11.4"
  },
  "devDependencies": {
    "@angular-devkit/build-angular": "^14.2.1",
    "@angular/cli": "^14.2.1",
    "@angular/compiler-cli": "^14.2.0",
    "@nguniversal/builders": "^14.1.0",
    "@types/express": "^4.17.0",
    "@types/jasmine": "~3.10.0",
    "@types/node": "^12.11.1",
    "jasmine-core": "~3.10.0",
    "karma": "~6.3.0",
    "karma-chrome-launcher": "~3.1.0",
    "karma-jasmine": "~4.0.0",
    "karma-jasmine-html-reporter": "~1.7.0",
    "typescript": "~4.8.2"
  },
  "browser": {
    "fs": false,
    "path": false,
    "os": false,
    "zlib": false,
    "net": false,
    "url": false,
    "stream": false,
    "crypto": false,
    "http": false,
    "querystring": false,
    "util": false
  }
} 

EDIT I finally found the culprit of all evil.

Don't use export variables defined on server-side (like in server.ts) in the AppModule...

Basically, this happened by my mistake and wrong import.

martin-mindflow commented 1 year ago

Facing this issue as-well, bumping for visibility. It would simplify a lot of our issues if this sloppy file could be replaced by strict compliant code. Is this something that could be contributed on ? I'm willing to take a look at it :)

Thanks a lot !

LuisGilGB commented 11 months ago

domino using with statements also results in build errors in Next JS 14.0.2 (also in 14.0.3): https://codesandbox.io/p/devbox/next-14-0-2-domino-build-error-bug-dylymw

domino is used as a dependency of turndown, which is itself a dependency of remirror, the module actually used in this sandbox app.

This specific bug is most likely an issue on how Next JS resolves the dependencies regarding JavaScript's strict mode in the latest versions; but domino relying on with statements is the root of many potential breaking changes wherever they're not expected, and that's a fact that cannot be ignored.

guidsen commented 8 months ago

Can someone look at this? It's a big issue for people migrating to Next.js 14 and using the turndown package

kavin-happyfox commented 7 months ago

In your project bundler's config, check for an option called browser and set it to true.

Because turndown has two versions of build files. One is for the browser and the other is for node env. The browser version doesn't have dependency on domino.

Screenshot 2024-03-25 at 9 13 03 PM

By setting the option browser:true in the bundler, it will include only the browser specific build files in your project bundles.

For rollup bundler, I use this plugin and the browser set to true and it worked like a charm.