I chose to do this as a new project to:
* Combine common and engine-specific modules in same package
* Remove all narwhal-specific module/package/sandbox code to focus on
utility modules
Initial supported platforms will be: node, jetpack, rhino
The idea is to be able to simply include the package in an existing
program and use the various narwhal modules vs having to bootstrap the
entire application with narwhal.
Once I have a bit more working I'll be posting links.
__HELP__: There are a couple of modules that I cannot locate the source
code for. These are:
require("narwhal/iconv-embedding");
require("narwhal/buffer-embedding")
Where can I find the implementations for these modules?
Also for nodejs I am porting the code from:
https://github.com/kriskowal/node/tree/narwhal-master/narwhal/lib
From memory, is there any reason why that node engine code should not
work with some adjustments?
I also found this module:
that refers to:
require("node/buffer-embedding")
that I cannot locate.
Thanks
Christoph
(I can't actually help with your problem. Kris can though)
-tom
> --
> You received this message because you are subscribed to the Google Groups "Narwhal and Jack" group.
> To post to this group, send email to narw...@googlegroups.com.
> To unsubscribe from this group, send email to narwhaljs+...@googlegroups.com.
> For more options, visit this group at http://groups.google.com/group/narwhaljs?hl=en.
>
Both of these were in my narwhal-node embedding (which I've abandoned
and had removed from my github to avoid sending people on
wild-goose-chases. I've put it back up with a tourist-deterring
description.)
https://github.com/kriskowal/narwhal-node
The iconv embedding for Node comes from my transcoding package too,
which is still published. It can probably be trivially provided with
any transcoder library.
https://github.com/kriskowal/transcode
The Buffer embedding just needs to export Node's Buffer API.
Kris Kowal
My goal is to be able to *easily* use narwhal modules cross-platform
without needing to boot my app with narwhal.
I want to simply be able to map narwhal:
package.json ~ {
"mappings": {
"narwhal": "http://narwhal/"
}
}
And use modules with:
require("narwhal/util");
require("narwhal/file");
Where platform/engine specific code would be automatically loaded if
needed by a module.
With PINF I have the ability to resolve the following require:
require("./platforms/{platform}/node/module");
Where "{platform}" gets replaced with the value of 'require.platform'
which is sufficient to load platform-specific code.
I think narwhal2 should consist of all modules + engine code in one
project vs having engine code in external projects. This will make it
easier to compare feature support for various engines, share modules in
various ways between engine code and long-term provide the ability to
reduce the engine-specific code to the foundation modules that CommonJS
will specify.
I have started using the following directory layout:
lib/<narwhal-lib modules>
lib/commonjs/ <- for specified APIs
lib/platform/<platform>/ <- engine specific code
Combine this with "{platform}" in require() and you have everything you
need to satisfy the requirements of the narwhal modules and can run this
on any supporting loader.
My goal is to contribute a continuous integration setup where we can
test all modules against all platforms. Once this is setup there is no
reason why narwhal cannot become the most portable utility library for
JS and lead the CommonJS spec process by implementation.
I am less interested in what narwhal provides in terms of it's package
and loader support unless we can bring it up to speed with the mappings
spec or provide sufficient hooks so I can splice in my own resolution
logic. This may actually be a good exercise to boil the core loader down
to it's minimum + plugin API. With PINF I use BravoJS for the core
loader and extend it with various plugins to implement the CommonJS
package and mappings specs. If narwhal can implement the same plugin
interfaces with a different internal implementation we are one spec
closer to have a portable loader plugin API.
One thing the narwhal loader system has that BravoJS does not is the
ability to easily create sub-namespaces via sandboxes. Sandboxes are
also a concept that I think would benefit from more rigid specification
long-term. I am not quite sure yet how deep they need to reach into the
loader or how that can be best achieved with minimal changes to a
loader. I hope to implement Sandboxes for BravoJS soon and will know
more once that is done.
So overall I am in complete support of a reboot and am willing to
contribute time and resources to address project quality, docs and
consistency. When it comes to porting the engine code I really need some
help as all the binary stuff and how that fits into the various
platforms is way over my head. I can contribute the 'jetpack' engine as
I am most familiar with it and can pull code from various places. How
the binary stuff fits into that we can discuss.
I think we could have this up and running fast. We just need to get the
basics setup and working on the popular platforms and can tweak from there.
Christoph
Sounds like a good goal, though it's not going to be my only goal.
>
> I want to simply be able to map narwhal:
>
> package.json ~ {
> "mappings": {
> "narwhal": "http://narwhal/"
> }
> }
>
> And use modules with:
>
> require("narwhal/util");
> require("narwhal/file");
>
> Where platform/engine specific code would be automatically loaded if needed
> by a module.
>
> With PINF I have the ability to resolve the following require:
>
> require("./platforms/{platform}/node/module");
>
> Where "{platform}" gets replaced with the value of 'require.platform' which
> is sufficient to load platform-specific code.
>
> I think narwhal2 should consist of all modules + engine code in one project
> vs having engine code in external projects. This will make it easier to
> compare feature support for various engines, share modules in various ways
> between engine code and long-term provide the ability to reduce the
> engine-specific code to the foundation modules that CommonJS will specify.
That's also probably a good idea. There's not a great reason for them
to be separate, except to allow 3rd parties to add their own engines
without our blessing, but they could still do that and have an
installation script to copy/symlink their engine into your narwhal
installation until we get it merged.
>
> I have started using the following directory layout:
>
> lib/<narwhal-lib modules>
Why not lib/narwhal/<narwhal-lib modules> like it currently is?
> lib/commonjs/ <- for specified APIs
I like this, it solves the problem of certain platforms providing
modules with naming conflicts with CommonJS. It also has the benefit
that if you only use APIs under the "commonjs" namespace your code is
guaranteed to work on any CommonJS platform that fully implements the
APIs (in theory, of course). It does make CommonJS appear less
important than the native modules the platform provides, but I'm ok
with that at this point.
> lib/platform/<platform>/ <- engine specific code
>
> Combine this with "{platform}" in require() and you have everything you need
> to satisfy the requirements of the narwhal modules and can run this on any
> supporting loader.
>
> My goal is to contribute a continuous integration setup where we can test
> all modules against all platforms. Once this is setup there is no reason why
> narwhal cannot become the most portable utility library for JS and lead the
> CommonJS spec process by implementation.
>
> I am less interested in what narwhal provides in terms of it's package and
> loader support unless we can bring it up to speed with the mappings spec or
> provide sufficient hooks so I can splice in my own resolution logic. This
> may actually be a good exercise to boil the core loader down to it's minimum
> + plugin API. With PINF I use BravoJS for the core loader and extend it with
> various plugins to implement the CommonJS package and mappings specs. If
> narwhal can implement the same plugin interfaces with a different internal
> implementation we are one spec closer to have a portable loader plugin API.
I would like for Narwhal to be something you can download and run out
of the box, you shouldn't have to go get a loader/etc from somewhere
else.
However we all have different ideas of what the best loader
implementation and extensions look like, so it would be nice if the
loader could be swapped out. That means Narwhal shouldn't rely on any
extensions to CommonJS and it should be easy to swap in different
loaders for different environments and maybe even use an existing
platform's loader (Node or Rhino or whatever).
Narwhal is basically:
1) JavaScript engine + some combination of shell scripts, JavaScript
code, and native code for bootstrapping into (2) and possibly (3)
2) CommonJS loader
3) command-line bootstrapping code, including argument parsing, etc
4) platform-specific standard library bindings
5) pure JavaScript standard libraries
I'd like for each of these to be de-coupled as much as possible.
1) Support several popular engines/platforms out of the box. Browsers,
Node.js, Rhino, Jetpack, etc.
2) Include a basic loader but be able to easily swap it out for other loaders.
3) Optional, especially for embedded environments like the browser,
Jetpack (?), Rhino embedded in an application or webserver, etc.
4) Depends on (5) but nothing else
5) Should be able to run this in ANY CommonJS environment without the
rest of Narwhal. Perhaps requires separating into platform APIs
(file/network/etc) and pure JS utilities (args, etc)
> One thing the narwhal loader system has that BravoJS does not is the ability
> to easily create sub-namespaces via sandboxes. Sandboxes are also a concept
> that I think would benefit from more rigid specification long-term. I am not
> quite sure yet how deep they need to reach into the loader or how that can
> be best achieved with minimal changes to a loader. I hope to implement
> Sandboxes for BravoJS soon and will know more once that is done.
All the loaders Kris K and I have written (after my initial one) have
been designed with this in mind. Basically you just need to
encapsulate everything in a "sandbox" object, never rely on globals. A
simple way to do that is just wrap your entire loader in function that
returns the root "require" function and call it "Sandbox" :)
Standardizing an API for creating new module loader sandboxes is a
good idea and probably will be part of the effort to make loaders
swappable in Narwhal2.
Narwhal is a cross-platform, multi-interpreter, general purpose JavaScript platform. It aims to provide a solid foundation for building JavaScript applications, primarily outside the web browser. Narwhal includes a package manager, module system, and standard library for multiple JavaScript interpreters. Currently Narwhal’s Rhino support is the most complete, but other engines are available too.Narwhal’s standard library conforms to the CommonJS standard. It is designed to work with multiple JavaScript interpreters, and to be easy to add support for new interpreters. Wherever possible, it is implemented in pure JavaScript to maximize reuse of code among engines.Combined with Jack, a Rack-like JSGI compatible library, Narwhal provides a platform for creating server-side JavaScript web applications and frameworks such as Nitro.
Right. This kind of workflow should be supported by the architecture we
choose.
>> I have started using the following directory layout:
>>
>> lib/<narwhal-lib modules>
>
> Why not lib/narwhal/<narwhal-lib modules> like it currently is?
To me narwhal is all about the modules you can use and the bootstrapping
just gets you to that point.
If you map the "narwhal2" package to "narwhal" via mappings and want
access to the narwhal modules as well as CommonJS then if you refer to a
narwhal module you would write require("narwhal/narwhal/module"). I can
work around this with PINF but other loaders are most likely less
flexible in this regard.
I would be fine with something like the following:
/lib/narwhal2/narwhal-engines
/lib/narwhal2/narwhal-boot
/lib/narwhal2/narwhal
/lib/narwhal2/commonjs
Where it is clear that the CommonJS modules for instance may rely on
narwhal modules and are a narwhal specific implementation.
>> lib/commonjs/<- for specified APIs
>
> I like this, it solves the problem of certain platforms providing
> modules with naming conflicts with CommonJS. It also has the benefit
> that if you only use APIs under the "commonjs" namespace your code is
> guaranteed to work on any CommonJS platform that fully implements the
> APIs (in theory, of course). It does make CommonJS appear less
> important than the native modules the platform provides, but I'm ok
> with that at this point.
I think we need to face the fact that native platform modules
(especially in the case of node) will always be used first by most
developers at least until CommonJS is further along.
I think we need to support gradual refactoring where developers can
start with native platform modules, later map in narwhal and selectively
start using or migrating to the CommonJS APIs and/or narwhal modules.
Until CommonJS is much more established having it live under narwhal
makes a lot of sense to me as our implementation will most likely not be
completely interoperable (for coordination and time reasons with other
projects).
I also think we need to run with the fact that other than
CommonJS/Modules/1(/2) the other specs will likely *not* be adopted
natively by most platforms at least in the short term. I think true
portability will only be achieved by projects such as narwhal or PINF
that shim the underlying platforms as needed and can provide a
consistent CommonJS foundation. In time this may put pressure on
platforms to implement some things more natively if the userbase is there.
If we let nodejs's lack of interest in CommonJS and portable
modules/packages lead us we will never get there. We need to build our
own community and apply pressure towards interoperability.
>> lib/platform/<platform>/<- engine specific code
>>
>> Combine this with "{platform}" in require() and you have everything you need
>> to satisfy the requirements of the narwhal modules and can run this on any
>> supporting loader.
>>
>> My goal is to contribute a continuous integration setup where we can test
>> all modules against all platforms. Once this is setup there is no reason why
>> narwhal cannot become the most portable utility library for JS and lead the
>> CommonJS spec process by implementation.
>>
>> I am less interested in what narwhal provides in terms of it's package and
>> loader support unless we can bring it up to speed with the mappings spec or
>> provide sufficient hooks so I can splice in my own resolution logic. This
>> may actually be a good exercise to boil the core loader down to it's minimum
>> + plugin API. With PINF I use BravoJS for the core loader and extend it with
>> various plugins to implement the CommonJS package and mappings specs. If
>> narwhal can implement the same plugin interfaces with a different internal
>> implementation we are one spec closer to have a portable loader plugin API.
>
> I would like for Narwhal to be something you can download and run out
> of the box, you shouldn't have to go get a loader/etc from somewhere
> else.
I agree, but use of the loader should be optional.
> However we all have different ideas of what the best loader
> implementation and extensions look like, so it would be nice if the
> loader could be swapped out. That means Narwhal shouldn't rely on any
> extensions to CommonJS and it should be easy to swap in different
> loaders for different environments and maybe even use an existing
> platform's loader (Node or Rhino or whatever).
Right. It should be no problem to achieve this internally by simply
relying on CommonJS/Modules/1. That is what PINF does during the
bootstrap process.
> Narwhal is basically:
>
> 1) JavaScript engine + some combination of shell scripts, JavaScript
> code, and native code for bootstrapping into (2) and possibly (3)
So basically provide a minimal API (such as FILE.exists(), FILE.read(),
...) that can be used by (2)?
> 2) CommonJS loader
I think the goal of this loader should be to only provide a simple
CommonJS/Modules/1 implementation that supports relative includes. That
is all that seems to be needed for further bootstrapping based on what I
learned from PINF.
> 3) command-line bootstrapping code, including argument parsing, etc
> 4) platform-specific standard library bindings
After (2) I think we need (4) and then boot into a new layer that
provides a fully-featured loader (or can delegate to an external loader).
(3) Should come after this and simply boot into the root sandbox
provided by the loader.
Having the minimal loader in (2) and fully featured loader after seems
to dramatically simplify the code. I think this is one of the key areas
narwhal needs to change. It currently tries to re-use too much code
during bootstrapping to the detriment of being able to wrap your head
around the process in a reasonable amount of time.
> 5) pure JavaScript standard libraries
These should be portable based on CommonJS/Modules/1 and only rely on
(4). This means we need to be able to statically require (4) modules
which is where {platform} comes in since we can only have string
literals for require().
> I'd like for each of these to be de-coupled as much as possible.
100% agree.
> 1) Support several popular engines/platforms out of the box. Browsers,
> Node.js, Rhino, Jetpack, etc.
+1
> 2) Include a basic loader but be able to easily swap it out for other loaders.
+1 I *will* be using PINF and can ensure that this is possible.
> 3) Optional, especially for embedded environments like the browser,
> Jetpack (?), Rhino embedded in an application or webserver, etc.
> 4) Depends on (5) but nothing else
> 5) Should be able to run this in ANY CommonJS environment without the
> rest of Narwhal. Perhaps requires separating into platform APIs
> (file/network/etc) and pure JS utilities (args, etc)
I don't think this is realistic initially. (5) will require (4) to
achieve portability for anything that touches the platform. Some logical
namespacing for different modules makes sense but separating based on
portability does not.
If you use only pure JS modules then static analysis tools will be able
to identify these for bundling or they should live in a completely
separate project (which is not my preference).
If you want portability (swap out narwhal) then you should choose to
code against the commonjs/* modules but I don't see these becoming
sufficiently implemented outside of narwhal to make that feasible in the
short term. I think you would be better off treating narwhal as your
portable layer on top of which your app runs.
My point is that we should not try and achieve portability by making
assumptions or set goals we cannot keep. Having an architecture that can
go from specific implementations to more general (read portable) ones by
developer choice is much more conducive to encourage progess in this
area. We need something that works today and can be adjusted to work
tomorrow.
>> One thing the narwhal loader system has that BravoJS does not is the ability
>> to easily create sub-namespaces via sandboxes. Sandboxes are also a concept
>> that I think would benefit from more rigid specification long-term. I am not
>> quite sure yet how deep they need to reach into the loader or how that can
>> be best achieved with minimal changes to a loader. I hope to implement
>> Sandboxes for BravoJS soon and will know more once that is done.
>
> All the loaders Kris K and I have written (after my initial one) have
> been designed with this in mind. Basically you just need to
> encapsulate everything in a "sandbox" object, never rely on globals. A
> simple way to do that is just wrap your entire loader in function that
> returns the root "require" function and call it "Sandbox" :)
Right. That works fine on the server. In the browser it is a bit more
complicated if loading modules via SCRIPT tags (read global entry
point). If you have multiple 'sandboxes' and load modules you need a
layer that memoizes the loaded modules in the correct sandbox. You may
also want to load the source once and then memoize it in multiple sandboxes.
I am glad we are having this discussion.
Christoph
Can I ask why else you don't like Narwhal?
Random thought regarding documentation: since the API docs for each platform should be identical for identical APIs, and there will be only one set of API tests, it seems documentation should live alongside the tests, rather than the implementation. API docs for each platform could be even be generated based on passing/failing tests tied to specific APIs (documentation could include warnings about failing tests, etc).
If you want to use full CommonJS packages and mappings with Ringo you
may want to take a look at my new loader project:
https://github.com/pinf/loader-js
It can sit on top of any platform and uses adapters to bootstrap a
fully-featured loader.
I would be happy to assist you in writing the adapter but it should be
trivial. See:
https://github.com/pinf/loader-js/tree/master/lib/pinf-loader-js/adapter
Christoph
That is along the lines of what I was thinking and will be working on.
> Which begs the question if these different JavaScript platforms all
> conformed to these tests then what would the point of Narwhal be? If
> Ringo were compatible with the rest of the Narwhal engines then we could
> abandon narwhal-rhino completely. I see Narwhal as filling in the gaps
> for minority JavaScript platforms and providing an easily bootstrap-able
> platform. Want CommonJS on Photoshop's JavaScript engine? (yes,
> Photoshop has a JavaScript engine) Throw together a basic Narwhal engine
> in a few hours like I did:
> https://github.com/tlrobinson/narwhal-photoshop How about Jetpack? Use
> the Narwhal engine. (what do you guys think of the tagline: "there's a
> Narwhal for that"... kidding. or not).
>
> There's also room for Narwhal to be the best browser CommonJS
> implementation, especially since so much of it is already implemented in
> JavaScript rather than the native language of each platform.
I have most of these goals working with my PINF loader including
seamless server/browser support. What is missing is narwhal-lib (with
platform/engine adapters) which is what spawned this thread.
I don't want to push for a change in the goals of Narwhal but maybe it
would make sense for the two projects to work together closely and have
narwhal focus on the library while PINF focuses on the bootstrapping and
loader.
If we start this way we can have something running very quickly as all
the hard stuff is already done and in a way that improves on narwhal1's
shortcomings that I mentioned. We could focus on getting narwhal-lib
working cross-platform and then decide if narwhal can or should improve
on the layers that the PINF loader provides.
This approach would be my preference overall as we can hit the ground
running and provide something to users right away.
What do you think?
Christoph