KnisterPeter/jreact

Missing __filename and __dirname

jsarman opened this issue · 10 comments

I am working on adding the __filename and __dirname virtual global vars, with no luck. I am at he point where I believe var f = new Function('require', 'exports', 'module', (require.transform ? require.transform(content) : content)); should be written as var f = new Function('require', 'exports', 'module', '__filename','__dirname', (require.transform ? require.transform(content) : content)); to give the require library the __ variables to conform to the updated version of node.js. Some modules use the __{var} to auto load extensions on server compiles. I have tried several attempts to set the scoped variables with no luck. Could you address this issue along with my attempts? A simple test is to require('showdown') which uses the __dirname to load extensions for server compiles. As of latest code it fails with __dirname being undefined. If I do solve this issue I will send a pull request, but at the moment I am stumped. Thanks for your support. John

Hi John,
I think the __filename and __dirname variables should be added to the 'new Function(...)'. Otherwise you will no inject them into the context of the function which is what you require.

I'll welcome every pull request. :)

But I guess you will have a bigger problem anyway. If you are using showdown (the markdown parser) it is written with strong nodejs dependencies (e.g. file-api).
You have to emulate that or use a JVM-nodejs compatible runtime (maybe try dynjs).

Best luck.

Showdown happened to be in an example I was testing. I ran into the
__dirname issue. My goal is to simply see how far I can go using nashorn to
eval the nodejs dependencies.
I did add the __dirname and __filename variables:
var f = new Function('require', 'exports', 'module',
'__filename','__dirname', (require.transform ? require.transform(content)
: content));
...
var __dirname = getDirectory(uri.uri);
var __filename = getFilename(uri.uri);
f.call({}, require, exports, module,__filename,__dirname);

where the new functions are
function getDirectory(path) {
if(isDirectory(path))
return getFilename(path);
return (new java.io.File(path)).getParent();
}
function getFilename(path) {
return (new java.io.File(path)).getName();
}

However I am missing how the parameters passed into the f.call are used.
In the actual nodejs, the call is wrapped using module.js and the
parameters are set in that file. How does the mock require you constructed
set the require, export, and module, or is that not actually being used?

Thanks,
John

On Mon, Jan 26, 2015 at 5:22 AM, Markus Wolf notifications@github.com
wrote:

But I guess you will have a bigger problem anyway. If you are using
showdown (the markdown parser) it is written with strong nodejs
dependencies (e.g. file-api).
You have to emulate that or use a JVM-nodejs compatible runtime (maybe try
dynjs).

Best luck.


Reply to this email directly or view it on GitHub
#1 (comment).

I don't get your question right I think?
require, module and exports are used internally and are the common-js api for the require call.

You can go all the way with rhino or nashorn (or any other compliant js-engine). Its just a matter for what dependencies you use and how much efford you put into emulating nodejs apis.

https://github.com/joyent/node/blob/master/lib/module.js

This is the common-js impl used in node.js as best I understand. Every
node module is wrapped in the the module.js
at line 378 in the above link

Module.prototype._compile = function(content, filename) {
....

which is used to Run the file contents in the correct scope or sandbox
In the function the follow are set.

sandbox.require = require;
sandbox.exports = self.exports;
sandbox.__filename = filename;
sandbox.__dirname = dirname;
sandbox.module = self;
sandbox.global = sandbox;
sandbox.root = root;

Then passed off to the actual call of the contents. Similar to f.call.

So my question is where do you set the globals for module, require and
exports in the emulating code. I could be barking up the wrong tree
here since I only have been working with JReact for a couple of days,
but I cannot find anywhere where the emulated require.js or jreact.js
actually uses these parameters, which would confirm why __dirname and
__filename are not able to be added.

Thanks

John

On Mon, Jan 26, 2015 at 5:58 AM, Markus Wolf notifications@github.com
wrote:

I don't get your question right I think?
require, module and exports are used internally and are the common-js api
for the require call.

You can go all the way with rhino or nashorn (or any other compliant
js-engine). Its just a matter for what dependencies you use and how much
efford you put into emulating nodejs apis.


Reply to this email directly or view it on GitHub
#1 (comment).

Just adding it as parameters in the Function and adding it to the apply-call will be sufficient to have them "globally" available.
Global is not really global, since the are only defined in the Function-scope. But thats the semantic one wants to archive with common-js.

That is what I did, and I apologize, I assumed the require('fs') called in
showdown was a npm module, but in fact it is a core functionality, which as
you stated needs to be emulated. I saw the error last night my time, and
read it as the same error of __dirname being undefined. However the error
was actually: Caused by: javax.script.ScriptException: TypeError: Cannot
call undefined in at line number 126 because the npm module fs
is not the same as the node builtin fs.

Thanks,
John

On Mon, Jan 26, 2015 at 6:27 AM, Markus Wolf notifications@github.com
wrote:

Just adding it as parameters in the Function and adding it to the
apply-call will be sufficient to have them "globally" available.
Global is not really global, since the are only defined in the
Function-scope. But thats the semantic one wants to archive with common-js.


Reply to this email directly or view it on GitHub
#1 (comment).

Any pull request with __dirname and __filename would be still great :)

Created the pull request. Also it includes extra check of the main from
package.json. showdowns main was "main": "./src/showdown" so I assumed
this is acceptable even though the actual file is src/showdown.js so I
added the check for .js in the code.

On Mon, Jan 26, 2015 at 7:32 AM, Markus Wolf notifications@github.com
wrote:

Any pull request with __dirname and __filename would be still great :)


Reply to this email directly or view it on GitHub
#1 (comment).

Thanks