Skip to content
This repository has been archived by the owner on Jul 24, 2024. It is now read-only.

Enable install and build using node-chakracore #1777

Closed
wants to merge 18 commits into from

Conversation

kunalspathak
Copy link

This PR enables windows user to install and locally build this module using node-chakracore. See nodejs/node-chakracore#136.

Individual commits have description of changes. If this is enabled, node-chakracore user can do the following in order to install node-sass module.

  • Open 'Node.js chakracore command prompt`
  • npm install

npm install would build the module locally using node-chakracore instead of downloading pre-built binary that is compiled with nodev8. See #1776.

Test result: All unit test pass.

  5908 passing (22s)
  322 pending

@xzyfer
Copy link
Contributor

xzyfer commented Nov 1, 2016

For clarification, the crux of the issue is that node-chakracore isn't compatible with node-gyp?

scripts/build.js Outdated
return ['--', subject, '=', process.env[subject.toUpperCase()] || ''].join('');
})).concat(options.args);

console.log(['Building:', process.execPath].concat(args).join(' '));
// To make node-chakracore work, check if node-gyp is in the path.
// If yes, use it instead of using node-gyp directly from node_modules because it might not be
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I find this comment to be rather misleading since it is only true if we're running under chakracore.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, I will updated the code to call out node-chakracore vs. node-v8.

scripts/build.js Outdated
if (useInstalledNodeGyp) {
exeName = 'node-gyp';
} else {
args.unshift(require.resolve(path.join('node-gyp', 'bin', 'node-gyp.js')));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I correct in assuming this will fail if process.jsEngine === 'chakracore'?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That's correct. This is the existing code that gets executed and fails for process.jsEngine === 'chakracore'.

@xzyfer
Copy link
Contributor

xzyfer commented Nov 1, 2016

Generally speaking I'm 💯 for support chakracore. However we will either fully support it, or not support it all. IMHO half way solution is poor a experience for user, and a potential burden on us the maintainers.

To get this over the line we'll need to do the following at a minimum

  • support chakracore in the binary resolution process i.e.getBinaryName
  • update the release target in .appveyor.yml to build chakracore binaries in CI
  • update the default target in .appveyor.yml to test against chakracore in CI

Of cause I'm more than happy to help with any of the above.

scripts/build.js Outdated
@@ -132,14 +132,31 @@ function build(options) {
process.exit(1);
}

var args = [require.resolve(path.join('node-gyp', 'bin', 'node-gyp.js')), 'rebuild', '--verbose'].concat(
['libsass_ext', 'libsass_cflags', 'libsass_ldflags', 'libsass_library'].map(function(subject) {
var args = ['rebuild', '--verbose'].concat(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move the node-gyp resolution logic into it's own function.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

@kunalspathak
Copy link
Author

@xzyfer , I have updated the PR to address the review comments. I have also updated to address getBinaryName() for different engines. By default (for nodev8) it will retain the existing format so released binaries will continue to work and downloadable.

It will be appreciated if you can take care of appveyor.yml changes.

scripts/build.js Outdated
args.unshift(require.resolve(path.join('node-gyp', 'bin', 'node-gyp.js')));
}

console.log(['Building:', exeName].concat(args).join(' '));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please move this back to the spawn call site.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure.

@@ -129,6 +129,11 @@ function checkAndDownloadBinary() {
if (sass.hasBinary(binaryPath)) {
return;
}

if (process.jsEngine && process.jsEngine === 'chakracore') {
Copy link
Contributor

@xzyfer xzyfer Nov 2, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't required with the changes to getBinaryName().

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

true.

@xzyfer
Copy link
Contributor

xzyfer commented Nov 2, 2016

@kamilogorek I'm happy to take a look. Is there any documentation to can recommend for getting node-chakracore update and running?

@kamilogorek
Copy link
Contributor

@xzyfer are you sure that you wanted to mention me? :)

@xzyfer
Copy link
Contributor

xzyfer commented Nov 2, 2016

@kamilogorek I did not, apologies.

@kunalspathak

I'm happy to take a look. Is there any documentation to can recommend for getting node-chakracore update and running?

@kamilogorek
Copy link
Contributor

@xzyfer no worries! glad I could help :)

@xzyfer
Copy link
Contributor

xzyfer commented Nov 2, 2016

I've opened a feature request with AppVeyor for Chakracore support. appveyor/ci#1148

@xzyfer
Copy link
Contributor

xzyfer commented Nov 2, 2016

@kunalspathak can you please follow the steps in https://github.com/blog/2247-improving-collaboration-with-forks so I can collaborate on this PR.

@kunalspathak
Copy link
Author

kunalspathak commented Nov 2, 2016

@xzyfer

can you please follow the steps

I have enabled "Allow edits from maintainers" for this PR.

Is there any documentation to can recommend for getting node-chakracore update and running?

In appveyor/ci#1148, you have already added link to node-chakracore's release page. One last thing is we need to build binding.node from Node.js (chakracore) command prompt that comes when node.js chakracore is installed.
Let me know if you need any other information to get this done.

binaryName = [process.platform, '-',
process.arch, '-',
process.versions.modules].join('');
process.versions.modules,
jsEngine].join('');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seeing this now, might be better to join('-') to simplfy this, then just add the jsEngine

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reason I didn't add is that would have changed the existing nodejs binary name with extra - added since process.jsEngine will be undefined. However I will change it to run through a .filter() followed by .join('-')

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a manditory change, I was just thinking this

     binaryName = [process.platform,
                   process.arch,
                  process.versions.modules].join('-');
     binaryName += process.jsEngine ? '-' + process.jsEngine : '';

But maybe that isn't any more readable :)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah. I was inclined towards something like this

binaryName = [process.platform,
                  process.arch,
                  process.versions.modules,
                  process.jsEngine]
                  .filter(function(val) {return val;}).join('-');

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Prefer _ if val is just a pass through.

.filter(function(_) { return _; });

Personally I prefer code to be explicit.

var binaryName = [
  process.platform,
  process.arch,
  process.versions.modules
];

if (process.jsEngine) {
  binaryName.push(process.jsEngine);
}

return binaryName.join('-');

scripts/build.js Outdated

// For node-chakracore, check if node-gyp is in the path.
// If yes, use it instead of using node-gyp directly from
// node_modules because the one in node_modules is not
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it just a matter of bumping to a newer version in package.json or are users expected to have a custom version that only ships with node-chakracore?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Users will have custom version of node-gyp that ships with node-chakracore.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since it looks like the only difference (by just browsing the History) for your copy of gyp looks like nodejs/node-chakracore@023b96c and nodejs/node-chakracore@3a09525. Have you tried to just upstream those changes to gyp? Then it would just be a matter of bumping the minimum node-gyp version

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, just noticed nodejs/node-gyp#873

@xzyfer
Copy link
Contributor

xzyfer commented Nov 2, 2016

@kunalspathak specifically I'm trying to install node-chakracore from the release binaries in our CI.

See my attempts in https://github.com/sass/node-sass/blob/trash/chakra/appveyor.yml#L122-L126
and the resulting build failure https://ci.appveyor.com/project/sass/node-sass/build/2103/job/23igf1j45b47bp0c

I'm not entire sure how to deal with the msi file in CI to get a functioning node.exe.

@nschonni
Copy link
Contributor

nschonni commented Nov 2, 2016

@xzyfer you might try the same as what AppVeyor does for the supported versions https://github.com/appveyor/ci/blob/master/scripts/nodejs-utils.psm1#L116

@kunalspathak
Copy link
Author

@xzyfer , regarding build failure, can you make sure that installed node is in the path? Also if you want to use same command prompt, you might want to call <node_chakracore_installation_path>\nodevars.bat which will set right environment variables.

@xzyfer
Copy link
Contributor

xzyfer commented Nov 2, 2016

can you make sure that installed node is in the path
@kunalspathak sorry for not being clear, my issue was that I don't know how to make an MSI file do those things :)

@nschonni aha this looks like what I was after. I took a look around that repo but got caught of the disparity between those function names and the ones in their docs.

@kunalspathak
Copy link
Author

@nschonni , there is extra customization that we did for node-chakracore installer in our private fork. You can diff below files for node vs. node-chakracore. It forces to use installed sdks/libs/headers rather than downloading from nodejs.org.

  • <node_installation_path>\node_modules\npm\node_modules\node-gyp\lib\configure.js

image

  • <node_installation_path>\node_modules\npm\node_modules\node-gyp\addon.gypi

image

@nschonni
Copy link
Contributor

nschonni commented Nov 2, 2016

I'll see if I can figure out what would be needed in the module to get AppVeyor to just natively support the install

@xzyfer
Copy link
Contributor

xzyfer commented Nov 3, 2016

I've updated this PR with the required AppVeyor config, as well tidying up the node-gyp resolution.

All that's missing is some jsdoc comments for the new functions we I think this is done.

appveyor.yml Outdated
- ps: Write-Host "Installing node-chakracore..." -ForegroundColor Cyan
- ps: Write-Host "Downloading..."
- ps: $msiPath = "$env:USERPROFILE\node-chakracore-$env:platform.msi"
- ps: $file = "https://github.com/nodejs/node-chakracore/releases/download/node-chakracore-7.0.0-pre9/node-chakracore-$($env:platform).msi"
Copy link
Author

@kunalspathak kunalspathak Nov 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xzyfer , what is the expectation here when we release new binary? Will we have to update this version?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is barrier to offering official support. We also will not release official release binaries until node-chakracore can a offer stable ABI. This PR will enable node-chakracore compatibility, but no support.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will not release official release binaries

Could you please elaborate on this? Do you mean that binding.node built using node-chakracore will not get hosted on https://github.com/sass/node-sass/releases ?

until node-chakracore can a offer stable ABI

You mean until node-chakracore binaries are not available on CI system of nodejs.org, right?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean that binding.node built using node-chakracore will not get hosted on

Correct. Installing node-sass with node-chakracore will fallback to local compilation as were you originally doing in this PR.

You mean until node-chakracore binaries are not available on CI system of nodejs.org

Exactly.

Copy link
Author

@kunalspathak kunalspathak Nov 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok.
In that case, I am confused about what was the intent of making .appveyor.yml changes as part of this PR? Was it a prep work so when node-chakracore binaries become available, we will update the download link and official support node-chakracore built binaries?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am confused about what was the intent of making .appveyor.yml changes as part of this PR

It was the best way IMHO to verify this PR is working as expected. As I originally stated we weren't willing to have hacks for node-chakracore when it doing the right way was just as easy.

Was it a prep work so when node-chakracore binaries become available

Correct. Also having CI working with chakracore gives us confidence in support it.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xzyfer Thanks for the clarification. Let me know if anything else is needed to get this merged.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@xzyfer , We have CI builds coming from last couple of days at here. Is there anything else you need to get this merged?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kunalspathak no. IMO this is ready to go it's just a matter of finding the appropriate time to release it. I suspect it will after LibSass 3.4 stable see #1800.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@kunalspathak are you able to update this to use nvs? Pinning this to an out dated version of node-chakracore isn't great

scripts/build.js Outdated
exeName = 'node-gyp';
} else {
args.unshift(require.resolve(path.join('node-gyp', 'bin', 'node-gyp.js')));
if (process.jsEngine && process.jsEngine === 'chakracore') {
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here, it is ok to check process.jsEngine === 'chakracore'

];

if (process.jsEngine) {
binaryName = binaryName.concat(binaryName);
Copy link
Author

@kunalspathak kunalspathak Nov 3, 2016

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should be binaryName.concat(process.jsEngine);

@kunalspathak
Copy link
Author

@xzyfer , I noticed some issues and fixed in recent commits. If they look good, feel free to merge it.

@matthargett
Copy link

/cc @rdy -- this fix allows node-chakracore to run pivotal-cf/react-starter with all tests passing (on Windows, anyway -- didn't test Linux/MacOS), resolving nodejs/node-chakracore#136 . There is a crash when the test runner exits, but that also happens with nodejs-v8 on Windows.

@kunalspathak
Copy link
Author

@nschonni - Is there a way to trigger the build again? Seems like appveyor.yml picked the old version of nvs.

@nschonni
Copy link
Contributor

nschonni commented Jul 11, 2017 via email

@kunalspathak
Copy link
Author

@nschonni - That was it. Fixed it.

@xzyfer
Copy link
Contributor

xzyfer commented Jul 12, 2017

Thanks again for all your work on this @kunalspathak and @nschonni

Copy link
Contributor

@nschonni nschonni left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM, just a few wrap up minor questions

*
* @api private
*/
function resolveNodeGyp() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we still need this now that the version is bumped to 3.6?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No and that's why i removed my changes in 5021dff . I just kept the resolution of node-gyp in separate function for easy readability.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍 that makes sense

appveyor.yml Outdated
GYP_MSVS_VERSION: 2015
APPVEYOR_BUILD_WORKER_IMAGE: Visual Studio 2015
- NODEJS_VERSION: chakracore/8.1.2
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will a plain chakracore/8 work here so we don't need to bump it regularly?

Copy link
Contributor

@xzyfer xzyfer Jul 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This raises the question of what kind of ABI guarantees we get with CharkraCore.

  • Can we continue to rely on process.modules.version as the ABI version?
  • Is CharkraCore supported by N-API?
  • What's the estimated time line on WASM support in CharkraCore?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

  • WASM has been in ChakraCore since 1.4
  • node-chakracore 8.x is included in the N-API repo ( @digitalinfinity)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @matthargett. I was under the impression from #1777 (comment) that WASM wasn't supported in node-chakracore. Can you please confirm?

Copy link

@digitalinfinity digitalinfinity Jul 13, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WASM is supported in Node-ChakraCore if you're using the WebAssembly methods from JavaScript. Using basic.wasm from here, the following code worked with Node-ChakraCore:

const fs = require('fs');
const buf = fs.readFileSync('basic.wasm')

async function test() {
    try {
        const module = await WebAssembly.compile(buf);
        const inst = new WebAssembly.Instance(module, {test: {foo: function(a){console.log(`foo called: ${a}`); return 2;}}});
        console.log(inst.exports.a(1));
    } catch (reason) { 
        console.log(`Failed: ${reason}`)
    }
}

test();

Note that ChakraCore doesn't expose JSRT APIs for embedders to directly invoke WASM from their applications- the workaround is they'll have to do it through JavaScript.

Also, minor technical point but while node-chakracore was included in the N-API repo during N-API prototyping, N-API has merged into the master branch of nodejs/node, so active N-API development for Node-ChakraCore is now happening in the master branch of nodejs/node-chakracore. But the meta point still stands that node-chakracore supports N-API.

@kunalspathak
Copy link
Author

kunalspathak commented Jul 13, 2017

@nschonni - I have fixed chakracore version to chakracore/8.

@kunalspathak
Copy link
Author

Thanks @nschonni and @xzyfer so far for shaping the PR. Let me know if you need anything else to merge this PR.

@saper
Copy link
Member

saper commented Jul 19, 2017

What are the process.versions.module values for chakracore engines? How often do they change? How many shall we support?

@kunalspathak
Copy link
Author

@saper - did you mean to say process.versions.modules. If yes, it is 57 currently and has same value as node-v8. We don't control it and it will be set from upstream node that we inherit.

@saper
Copy link
Member

saper commented Jul 19, 2017

Thanks. This is mainly used to denote changes in the V8 API, I thought Chakra might have come up with something different?

@saper
Copy link
Member

saper commented Jul 19, 2017

In other words: suppose I have downloaded a chakracore node-sass binary module 57 today. How would I know I need a new one, say, 6 months from now? Is ABI stability guaranteed? We have lots of problems with users forgetting to update their modules.

@kunalspathak
Copy link
Author

It should work similar to way it works with node-v8. So lets say in future node.js 10.X , the modules version was updated to say 79, when we release node-chakracore from 10.X branch, it will have same module versions i.e. 79 because to release that we would have shimmed required v8 APIs . Does that make sense ?

@saper
Copy link
Member

saper commented Jul 19, 2017

Do I understand this correctly @kunalspathak that chakracore is V8-API compatible? If so, what is breaking ABI compatibility, so that the existing binaries cannot be used?

@kunalspathak
Copy link
Author

chakracore is V8-API compatible

Yes. In order for node-chakracore to work we shim all the V8 APIs that node or a native module calls into.

@saper
Copy link
Member

saper commented Jul 19, 2017

ok, that solves the API problem, i.e. module compiled by hand should generally work.

How do we ensure ABI compatibility between modules?

Examples on situations where ABI may work:

  • You are bumping ChakraCore engine version (for example from 1.5.2 to 1.5.3). It may or may not break the ABI - both ChakraCore engine versions are attached to NODE_MODULE_VERSION 57.
  • You decide to do some changes in the chakrashims: for example you decide to allow more than 8 local variables on the stack and therefore bump kOnStackLocals to something else, which will almost probably break ABI.

Even today, will node-sass binding.module compiled with ChakraCore 1.5.2 work with 1.5.3? Is the reverse true?

(I cannot get ChakraCore to build, so I cannot test at the moment).

This is a major concern from my side - if we are to offer binary module downloads, ABI stability must be guaranteed.

@kunalspathak
Copy link
Author

kunalspathak commented Jul 19, 2017

This is a major concern from my side - if we are to offer binary module downloads, ABI stability must be guaranteed.

That is a valid concern. However ABI compatibility is guaranteed by chakrashim and not chakracore. So even if we switch chakracore versions, as long as chakrashim is v8 API compatible, it should just work.

for example you decide to allow more than 8 local variables on the stack and therefore bump kOnStackLocals to something else

I am not sure how this will break the compatibility. This is purely chakrashim's optimization that is nothing to do with breaking compatibility.

@saper
Copy link
Member

saper commented Jul 19, 2017

If my binding is compiled with kOnStackLocals = 8 and v8handlescope.cc coming from the updated ChakraCore uses, say, 16, couldn't that lead to a mismatch in the size of HandleScope ?

In general: can we have something that will be bumped whenever one of the deps/ exposed to the modules changes?

@kunalspathak
Copy link
Author

In general: can we have something that will be bumped whenever one of the deps/ exposed to the modules changes?

We could have that, but the plan is not to diverge chakrashim from v8 headers unless v8 changes come from upstream. So in that case, version will only get bumped when upstream bump the version.

@xzyfer
Copy link
Contributor

xzyfer commented Jul 20, 2017

I touched on some of these concerns earlier. IIRC we greatly reduce risk from ABI changes by adopting N-API which is very close on our road map, and may land in the same release as this.

@kunalspathak
Copy link
Author

@xzyfer , do you have an ETA on when this can land?

@saper
Copy link
Member

saper commented Jul 22, 2017

This is a volunteer-driven project, so no ETAs here. I am concerned with releasing something quick now and worry about future compatibility "later".

@kunalspathak
Copy link
Author

Sorry @saper , I didn't mean to pressurize to land this PR prematurely. Its been a while the PR is open and I thought I addressed all the concerns. Let me know if there are any other issues that you want me to address and I will be happy to fix them.

@davej
Copy link

davej commented Aug 30, 2017

@kunalspathak Would you consider maintaining a fork and publishing to npm? Would love to use this as many of my frontend projects are constantly requiring re-builds when I upgrade node. Usually node-sass is the only native dep so would love to use this.

@kunalspathak
Copy link
Author

Thanks for asking @davej , but I am not sure if I understand your problem. This PR simply adds a support to build and work with node-chakracore. When you upgrade node, you might still need to rebuild.

@davej
Copy link

davej commented Aug 30, 2017

@kunalspathak sorry I skimmed the issue and saw a mention of N-API and assumed that's what the PR was about.

@nschonni
Copy link
Contributor

Sorry, closing since ChakraCore node is archived right now

@nschonni nschonni closed this Apr 21, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants