MoLow / ng-node-compile

Compile html templates the angular way, in node js
14 stars 7 forks source link

Cannot set property length of [object Object] which has only a getter #2

Closed butaixianran closed 9 years ago

butaixianran commented 9 years ago

Even with the given sample, it still can't work at all.

Always gives this error:

Angular enviorment not yet ready Cannot set property length of [object Object] which has only a getter

This is what I tried:

var ngcompile = require('ng-node-compile');
var ngEnviorment = new ngcompile();
ngEnviorment.$interpolate("hello {{name}}")({ name: 'Jhon doe' });

I'm using latest iojs.

Is there anything missed?

MoLow commented 9 years ago

Hmm. I think it is an issue with jsdom, wich for some reason works diffarently in io.js then in node. hope to look into it this weekend

butaixianran commented 9 years ago

On jsdom's project page, they said, jsdom works only with io.js, not with node.js anymore. https://github.com/tmpvar/jsdom

And I noticed a package called jsdom-nogyp used here, which havn't been updated for at least 2 years.

Hopefully, replace jsdom-nogyp with jsdom could fix this.

butaixianran commented 9 years ago

get same error with node v0.11.14

MoLow commented 9 years ago

well i guess using Jsdom is probably better for io.js. the problem is the jsdom 3.x versions which are supported in node.js use contextify, which is a big trouble mainly in windows, but also in isn't a big fun in linux. https://github.com/tmpvar/jsdom/tree/3.x. Maybe I will release a newer version which uses jsdom , not jsdom-nogyp, so it could be supported also in io.js. feel free until I have some time to look into it, to fork the repo, and to try playing around!

butaixianran commented 9 years ago

hi, after some testing, I think Jsdom version is not the problem!

The problem is, jsdom.env is a Async function!

Which means, when ngEnviorment.$interpolate is called, jsdom.env is still running, haven't done yet!

So, this.ready will always be false!!

MoLow commented 9 years ago

I actually also added a method onReady, so this may help:

var ngEnviorment = new ngcompile();
ngEnviorment.onReady(function () {
    ngEnviorment.$interpolate("hello {{name}}!")({ name: 'Jhon doe' })
});

Dident document it yet either. PLS tell me if it helped

butaixianran commented 9 years ago

I just updated to get onReady method, but also get a lot of errors here:

  1. line 17, this.envReady is undefined, and always throw a error.
  2. line 13, _self is undefined.
  3. line 31, angular is undefined
  4. method: .prototype.env is never used.

Seems some code which should be in jsdom.env now is outside it and may not work.

Too many errors... it totally doesn't work now. And you may need jshint.com to check code errors.

MoLow commented 9 years ago

could you show me your code? it seems you aren't calling the constructor or something.

MoLow commented 9 years ago

Ok then! I just tested with IO.js, and it seems jsdom is our problem. so I added a version to support io.js. works on my machine. update me what's with your machine.

10x alot for your involvement!

butaixianran commented 9 years ago
hi, I think your native code must be very different from this github repo.

When I run, I always get "Angular enviorment not yet ready".

This is the code I tried:

var ngEnviorment = new ngcompile();
ngEnviorment.onReady(function () {
    ngEnviorment.$interpolate("hello {{name}}!")({ name: 'Jhon doe' })
});
So I reviewed your code in "main.js" again, still find a lot of errors there:
And your jsdom still doesn't work.

Here is the issue: In your package.json, you set jsdom as ^4.0, which will download jsdom 4.5.2 when install ng-node-compile.

But jsdom 4.5.2 doesn't work anymore, it will give an error:

ng-node-compile/node_modules/jsdom/lib/jsdom/browser/Window.js:41 this._document = new dom.HTMLDocument({

To make jsdom works with ng-node-compile, you need latest jsdom, which is 5.6.1.

I tested all these both in windows and linux.

MoLow commented 9 years ago

could you pls run the tests in the test folder using mocha? thanks. it worked for me & also tested with travis:

https://travis-ci.org/MoLow/ng-node-compile

butaixianran commented 9 years ago

I test again and again, always the same error: Error: Angular enviorment not yet ready

at new ngCompile (/home/ubuntu/workspace/test/node_modules/ng-node-compile/main.js:29:46)
This is Line 29 of main.js:
if (!ngCompile.prototype.envReady) throw new Error(ENVIORMENT_NOT_READY);

This line says, when we run:

var ngEnviorment = new ngcompile();

If ngCompile.prototype.envReady doesn't exist, then throw an error.

But you haven't set any value to ngCompile.prototype.envReady yet, so it will always be undefined. Then this line always throw an error.

Another example:

Line 58:

ngCompile.prototype.env = jsdom.env({......});

ngCompile.prototype.env is never used, I can't find any line in your code which used this function.

If you just try to run jsdom.env when "new ngcompile();" But jsdom.env is an Async function, Line 29:

if (!ngCompile.prototype.envReady) throw new Error(ENVIORMENT_NOT_READY);

will always be run before jsdom.env can be done.

You can't just run an Async function and hope this Async function is fast enough, so it can be done before Line 29 runs.

Since Line 29 always be run before anything else, then Angular env will never be set up.

Anyway, I forked this repo and fixed it (based on version 1.5.5): https://github.com/butaixianran/ng-node-compile-fork/blob/master/main.js

This fix is not very good, it need to use this package like this:

var ngcompile = require('ng-node-compile-fork');

var ngEnviorment = new ngcompile();
// build angular env
ngEnviorment.env();
ngEnviorment.onReady(function () {
    var result = ngEnviorment.$interpolate("hello {{name}}!")({ name: 'Jhon doe' });
});

But it works, for now.

MoLow commented 9 years ago

Hmm, I see what you have done here. I should probably move the entire env function into the constructor.

MoLow commented 9 years ago

well, I have done somthing else. try this:

var ngcompile = require('ng-node-compile');
ngcompile.prototype.onEnvReady(function(){
    var ngEnviorment = new ngcompile();
    ngEnviorment.$interpolate("hello {{name}}")({ name: 'Jhon doe' });
});

and if even that did not work, then this should:

var ngcompile = require('ng-node-compile');
ngcompile.prototype.onEnvReady(function(){
    var ngEnviorment = new ngcompile();
    ngEnviorment.onReady(function(){
        ngEnviorment.$interpolate("hello {{name}}")({ name: 'Jhon doe' });
    });
});

again, thanks a lot for helping improve this package!

butaixianran commented 9 years ago

hi, both ways work now.

The reason I put jsdom.evn outside constructor is that I'm trying to make it work with Koa, not Express.

I'm not fan of callback hell. So I tried to wrap .env into a promise to make it yieldable. But failed...

I may try later if I can find a solution to wrap jsdom.env into a promise.

MoLow commented 9 years ago

Well, I'll convert it to use promises. the thing is, when using with express, you first require ng-node-compile, which runs the env function, then when a route in express is called, the env is ready, so there is no real need to use ng-node-compile the async way. I have nod idea what the use with Koa looks like, and why shoulden't it behave similar to express, regarding to first requiring the package. so anyway ,i'll change from callbacks to promises.