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

Using const or let in global scope have problem in nodejs actions #1728

Closed
csantanapr opened this issue Jan 16, 2017 · 12 comments
Closed

Using const or let in global scope have problem in nodejs actions #1728

csantanapr opened this issue Jan 16, 2017 · 12 comments
Labels

Comments

@csantanapr
Copy link
Member

Creating an action with variables declare in the global scope using const or let
then accessing this variables inside the main produce errors.

Bug found by user @cfjedimaster:
Here is an example to reproduce:

const foo = "foo";
let bar = "bar";

function main(){

  return {
    foo: foo,
    bar: bar,
  };
}

changing to use var then it works

Running as a zip action it doesn't have this problem, but running as a simple file (i.e. eval) it has this problem.

Produce the following error

"error": "Initialization has failed due to: ReferenceError: main is not defined\n    at eval (eval at \u003canonymous\u003e (/nodejsAction/runner.js:80:57), \u003canonymous\u003e:1:1)\n    at NodeActionRunner.init (/nodejsAction/runner.js:80:45)\n    at doInit (/nodejsAction/src/service.js:134:31)\n    at initCode (/nodejsAction/src/service.js:80:24)\n    at /nodejsAction/app.js:61:13\n    at Layer.handle [as handle_request] (/nodejsAction/node_modules/express/lib/router/layer.js:95:5)\n    at next (/nodejsAction/node_modules/express/lib/router/route.js:131:13)\n    at Route.dispatch (/nodejsAction/node_modules/express/lib/router/route.js:112:3)\n    at Layer.handle [as handle_request] (/nodejsAction/node_modules/express/lib/router/layer.js:95:5)\n    at /nodejsAction/node_modules/express/lib/router/index.js:277:22"
@csantanapr
Copy link
Member Author

@bjustin-ibm might be good to look into this one.

It most be something todo with on how we use eval and the scoping it creates

@psuter
Copy link
Contributor

psuter commented Jan 16, 2017

FWIW, this is "documented" here:

Note that main must be declared either as a function or as a var, due to the scoping rules for const and let which make such declarations invisible to the action runtime.

@cfjedimaster
Copy link
Contributor

I'm confused - my main was a function. It is as well in the code above.

@csantanapr
Copy link
Member Author

@psuter It's not very clear the statement just said that main needs to be declare as a function, which I'm already doing.

@csantanapr
Copy link
Member Author

I think this is a limitation that we would end documenting, but first would like to understand the root cause on why behaves this way.

@psuter
Copy link
Contributor

psuter commented Jan 16, 2017

Sorry, I read your example too quickly. You have indeed demonstrated a more general instance of the problem than the one I wrote about in the blog post: any top-level const or let is invisible to the runtime, main is just one potentially.

@csantanapr
Copy link
Member Author

csantanapr commented Jan 20, 2017

I never really super fan this eval hackery it feels like magic.

I proposed we look into writing the file int tmpfs (i.e. memory) and then do a clean require("./tmpfs/action.js")

I think it's important to fix this, as I can see a lot people using let or const and maybe other context related problems.

We would need to tell folks to make a migration some how that user will need to export.main = main

OR we could try to eval, catch the exception, and then do the require procedure, for a period to allow for migration.
We could also try to append export.main = main at the end of the file

@ioana-blue
Copy link
Contributor

Someone bumped into this issue and when I was asked for help, I was confused by the error as well. The example was a top-level const.

@starpit
Copy link
Contributor

starpit commented Feb 1, 2017

shouldn't we be doing the module wrappering at creation time? why wrapper it on every invocation?

we already support zip actions, and these impose an "action-as-module" requirement. so, to start with, the wsk CLI could turn any single-file javascript actions into zip actions, and upload the zip. that might solve most of the use cases, without having to mess with the invoker or any back-end bits.

(another point against eval: it obfuscates stack traces)

@csantanapr
Copy link
Member Author

Good idea @starpit but I would hold on doing something in the CLI just yet.
This will leave the problem for existing actions already in the DB that are not zip.
I think in general is a good approach to eventually have all actions as zip in the DB, but would do it in a way to keep a good UX.

I think for now, we update the nodejs proxy code, to take the string, append exports.main=main; and then write to file and do a require on the file, this will work for new actions and old actions already in the DB.

Then have the cli help building the zip, and would be also good to store the zip as an attachment in the DB which @rabbah said that's the direction.
This would give the ability to do a get on the action get, and not get back a zip file.
This leaves open the ability to someone make it very fast to retrieve just the source code, but what about if I want everything from the zip except the big node_modules folder.

One crazy idea was to save the action as two attachments one for the node_modules content and a second one for anything outside, this will allow something like a Web App UI and CLI be very efficient to retrieve the source code in a browser UI and ignore the node_modules.

@tardieu
Copy link
Contributor

tardieu commented Mar 1, 2017

I submitted PR #1929 to address this issue. It uses a function scope as opposed to a module to bypass the filesystem (avoid the temporary file).

tardieu added a commit to tardieu/openwhisk that referenced this issue Mar 2, 2017
tardieu added a commit to tardieu/openwhisk that referenced this issue Mar 3, 2017
tardieu added a commit to tardieu/openwhisk that referenced this issue Mar 7, 2017
tardieu added a commit to tardieu/openwhisk that referenced this issue Mar 7, 2017
@csantanapr
Copy link
Member Author

@rabbah close or anything else need it? 🙏
#1929 is merged now.

@rabbah rabbah closed this as completed Mar 10, 2017
dubee pushed a commit to dubee/openwhisk that referenced this issue Mar 10, 2017
dubee pushed a commit to dubee/openwhisk that referenced this issue Mar 10, 2017
houshengbo pushed a commit to houshengbo/openwhisk that referenced this issue Jun 23, 2017
jonpspri pushed a commit to jonpspri/openwhisk that referenced this issue Jul 4, 2017
houshengbo pushed a commit to houshengbo/openwhisk that referenced this issue Nov 13, 2017
houshengbo pushed a commit to houshengbo/openwhisk that referenced this issue Nov 13, 2017
houshengbo pushed a commit to houshengbo/openwhisk that referenced this issue Nov 14, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

7 participants