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

[JavaScript Linting] Support ESNext (async/await, class properties, etc) #3160

Closed
ndugger opened this issue Dec 6, 2016 · 18 comments
Closed

Comments

@ndugger
Copy link

ndugger commented Dec 6, 2016

I'm suggesting to change the javascript hinting to use ESLint for better support of ES6+ features.

I'd like to be able to use class properties and async/await the most, but there are also tons of other linting rules that it does much better than jshint.

class Foo {
    bar = 'baz';
}
async function foo () {
    const bar = await baz();
}

I haven't looked into how difficult this might be to swap out the javascript linter, so I don't know how realistic of a request this is.

@adamjimenez
Copy link
Contributor

This is a good idea and also needed for #3180.
We could base it off of the web demo files for ESLint.

@ozomer
Copy link

ozomer commented Sep 28, 2018

Pleaaaase work on this issue.

@DCzajkowski
Copy link

New JSHint version 2.10.0 has been released with support for the new features.

@vitrilo
Copy link

vitrilo commented Jul 29, 2019

As temp workaround - I've used ACE typescript, it already have await/async.

@manjukas
Copy link

Typescript doesn't show an error.. but then it misses a lot of other errors.

@bahaaaldin214
Copy link

its not just async/await its all es6 syntax including new math operators like 8**2

@Smolations
Copy link

Smolations commented Dec 6, 2019

As of today, this issue is 3 years old. React has been out awhile now so surely the demand is increasing for this. The project is still pretty active, but there is no indication of this being on any official roadmap and just seems like it's a, "yea that's what we need to do, and we're probably gonna do it."

Can we please get some sort of update here? @nightwing ? @adamjimenez ?

@gingerchew
Copy link

gingerchew commented Jan 20, 2020

I found this while trying to find the linter for CSS files, and jury rig something of my own, /mode/javascript_worker.js 🔗

This config seems to suggest that it is already set up for ESNext support , at least when working in Javascript worker mode for the javascript worker. Personally this didn't shed any light, but maybe this can help out one of y'all

@manjukas
Copy link

I tried re-building ace after replacing the jshint.js file with the latest. This prevents an error being shown for async/await. However it also stops errors being shown for other scenarios (missing brackets, unclosed strings, etc). Very frustrating, I suppose the ace project is dead.

@sharq88
Copy link

sharq88 commented Nov 23, 2020

I've been fiddling with this too and I was able to make it work. Documentation could be updated, it was rather painful to dig out how the whole ecosystem works (took several hours) and then learned that all change was needed is one line... :/

There are a couple of options:

  1. if you just imported the packaged/minified version - need to replace: "esnext:!0" with "esversion:9"
    https://raw.githubusercontent.com/ajaxorg/ace-builds/master/src-min/worker-javascript.js
  2. you can check out the repo and build yourself. (It takes about 1 minute, so this also rather easy)
git clone git@github.com:ajaxorg/ace.git
npm install
nano +82 lib/ace/mode/javascript_worker.js // replace "esnext: true," with "esversion: 9"
node Makefile.dryice.js full --target ../ace-builds

UPDATE: Since my last comment found another way:

var editor = ace.edit("editor");
editor.session.on('changeMode', function(e, session){
	if ("ace/mode/javascript" === session.getMode().$id) {
		if (!!session.$worker) {
			session.$worker.send("setOptions", [{
				"esversion": 9,
				"esnext": false,
			}]);
		}
	}
});
editor.session.setMode("ace/mode/javascript");

@gingerchew
Copy link

Awesome!! Any indication if you could specify other versions, like 6 for ES6 and so on?

I'll also add, in case others are new to git or haven't set up their SSH with Github, you can also clone it with: git clone https://github.com/ajaxorg/ace.git/. Stumbled on that one more times than I'd like to admit

@dreamsavior
Copy link

Is @sharq88 method still can be used on the latest ACE?
Because I still have the error even after implementing both of the method:

image

@chumager
Copy link

chumager commented Dec 26, 2021

Hi @dreamsavior, you can't use await outside an async function, unless you use the new javascript modules (import, export).
Javascript await.

AFAIK jshint can't know if you're using js modules or commonJS, because it has no configuration for this, you can check in jshint configuration, so it's not an ACE problem, it's a jshint problem.

It's a sad ECMA definition, because node.js (in some cases) and chrome supports await out of the box.

direct node eval.

node -e "console.log(new Date()); await new Promise(r=>setTimeout(r,1000));console.log(new Date());"
[eval]:1
console.log(new Date()); await new Promise(r=>setTimeout(r,1000));console.log(new Date());
                         ^^^^^

SyntaxError: await is only valid in async functions and the top level bodies of modules
    at new Script (node:vm:100:7)
    at createScript (node:vm:257:10)
    at Object.runInThisContext (node:vm:305:10)
    at node:internal/process/execution:75:19
    at [eval]-wrapper:6:22
    at evalScript (node:internal/process/execution:74:60)
    at node:internal/main/eval_string:27:3

node with package.json with type: module

cd /tmp
mkdir await_test
cd await test
echo '{"type": "module"}' > package.json
echo "console.log(new Date()); await new Promise(r=>setTimeout(r,1000));console.log(new Date());" > index.js && node .
2021-12-26T16:32:51.557Z
2021-12-26T16:32:52.564Z

direct node execution

node
Welcome to Node.js v16.13.1.
Type ".help" for more information.
> console.log(new Date()); await new Promise(r=>setTimeout(r,1000));console.log(new Date());
2021-12-26T16:34:30.794Z
2021-12-26T16:34:31.797Z
undefined
>

from Chrome
image

As you can see, the behavior is not standard... so there is no way to know if you can or can't use await outside an async function.

Regards.

EDIT: if your code is correct you can always use jshint directives from documentation

// Code here will be linted with JSHint.
/* jshint ignore:start */
// Code here will be ignored by JSHint.
/* jshint ignore:end */
ignoreThis(); // jshint ignore:line

@dreamsavior
Copy link

@chumager
Thank you for your time.
I well aware of the await that can not be used unless it is inside the async function OR THE TOP LEVEL BODIES OF MODULE.
In this case, I build an application to let the user create a custom script with the scope of TOP LEVEL BODIES OF MODULE. Hence, the script should consider that.
Also, thank you for pointing out the option to force jshint ignoring some line. But I guess, I can not force my users to use that technique each time they wrote await call.

@andrewnester
Copy link
Contributor

As specified above, JSHint has been updated to support these new language features and in order to enable it you need to add the following code

var editor = ace.edit("editor");
editor.session.on('changeMode', function(e, session){
	if ("ace/mode/javascript" === session.getMode().$id) {
		if (!!session.$worker) {
			session.$worker.send("setOptions", [{
				"esversion": 9,
				"esnext": false,
			}]);
		}
	}
});
editor.session.setMode("ace/mode/javascript");

@quinton-ashley
Copy link

quinton-ashley commented Jul 31, 2022

You guys should just set the default esversion higher for the linter. What kind of JS dev isn't using async/await in 2022? It took me half an hour to find out how to do it by finally finding this issue.

@RealSput
Copy link

As specified above, JSHint has been updated to support these new language features and in order to enable it you need to add the following code

var editor = ace.edit("editor");
editor.session.on('changeMode', function(e, session){
	if ("ace/mode/javascript" === session.getMode().$id) {
		if (!!session.$worker) {
			session.$worker.send("setOptions", [{
				"esversion": 9,
				"esnext": false,
			}]);
		}
	}
});
editor.session.setMode("ace/mode/javascript");

I have tried using this but it still errors, is there a way to fix this?
image

(here's some code, for reference):

<!DOCTYPE html>
<html lang="en">

<head>
    <title>ACE in Action</title>
    <style type="text/css" media="screen">
        #editor {
            position: absolute;
            top: 0;
            right: 0;
            bottom: 0;
            left: 0;
        }
    </style>
</head>

<body>

    <div id="editor">const fs = mod('fs');
        let inp = await input("Enter something here: ")
        fs.writeFileSync('/test.txt', inp);
        let oth_inp = await input('The string "'+inp+'" has been saved to test.txt. Would you like to view it? (Y/N)');
        if (oth_inp.toUpperCase() == "Y") {
        print(fs.readFileSync('/test.txt').toString());
        exit(0);
        } else if (oth_inp.toUpperCase() == "N") {
        print("OK, exiting..");
        exit(0);
        } else {
        print("Not an option!!");
        exit(1);
        } </div>

    <script src="https://cdnjs.cloudflare.com/ajax/libs/ace/1.13.1/ace.js" integrity="sha512-IQmiIneKUJhTJElpHOlsrb3jpF7r54AzhCTi7BTDLiBVg0f7mrEqWVCmOeoqKv5hDdyf3rbbxBUgYf4u3O/QcQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
    <script>
        var editor = ace.edit("editor");
        editor.setTheme("ace/theme/monokai");
        editor.session.on('changeMode', function(e, session) {
            if ("ace/mode/javascript" === session.getMode().$id) {
                if (!!session.$worker) {
                    session.$worker.send("setOptions", [{
                        "esversion": 9,
                        "esnext": false,
                    }]);
                }
            }
        });
        editor.session.setMode("ace/mode/javascript");
    </script>
</body>

</html>

@chris-heathwood
Copy link

chris-heathwood commented Jul 20, 2023

In case anyone else finds this thread whilst googling for this issue in react (using react-ace) do the following:

  const mode = 'javascript';

  const onLoad = ({session}: Ace.Editor) => {
    // Allow the latest js features in the editor, see https://github.com/ajaxorg/ace/issues/3160.
    // AceEditor does not seem to expose any of the js worker options, using a similar approach to this works.
    if (mode === 'javascript') {
      /* eslint-disable @typescript-eslint/ban-ts-comment */
      // @ts-ignore
      if (session.$worker) {
        // @ts-ignore
        session.$worker.send('setOptions', [{
          'esversion': 11,
          'esnext': false,
        }]);
      }
    }
  }

  <AceEditor
    mode={mode}
    onLoad={onLoad}
  />

And thanks @sharq88 for the fix 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests