Re: Remarks about module import

2008-08-23 Thread Peter Michaux
I'm a bit late to this module party...

On Tue, Aug 19, 2008 at 1:00 AM, Ingvar von Schoultz
[EMAIL PROTECTED] wrote:

  From the descriptions it looks like this could instead use
 a syntax based on destructuring assignment, if es-harmony
 will have destructuring:

 var {toggle: t, set: s} = import
 (   fetchModule ('http://foo.com/someModule.js'),

Are module and file synonymous? See

http://dev.helma.org/wiki/Modules+and+Scopes+in+Helma+NG/

What do the contents of the http://foo.com/someModule.js file look like?

fetchModule would need to work with the local file system for server-side work.

What exactly does fetchModule return? Some kind of first-class Module
class instance or is it returning the object which is being
destructured?

 {document: doc, background: bg}

What does this argument to import do?

 );
 t();

[snip]

Peter
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-23 Thread Kris Kowal
On Mon, Aug 18, 2008 at 1:44 PM,  [EMAIL PROTECTED] wrote:
 Hi folks,
 The module system proposals, especially the one here --
  http://wiki.ecmascript.org/doku.php?id=proposals:modules

Oh, a module party!  Sorry I'm late and thanks to Peter Michaux for
alerting me that I was missing out.  Ihab, if you recall, I met you
and The Mikes last December to talk about module systems.  I really
like the direction of this thread and thought I'd put in a couple
cents.  A lot of the things I want from a module system have already
been mentioned, so some of this is just a reiteration of some of the
great ideas that have been posed; some beg distinctions.

We do not need to preserve notions of eval, particularly that the last
statement evaluated be the module object.  I think that's a great idea
and vehicle for explicit exports, but consider this one: perhaps
modules can conceptually be constructors for capability objects that
are frozen and returned by some require function or, by extension,
some syntax that ultimately calls said require function.

Just to be explicit, I think that, if module A imports module B,
module B must have a special scope chain and context object.  Solely
by virtue of having been imported, we could distinguish it from a
legacy script, even if module A isn't a new-style module.  The context
object would be the module object itself, that you would add
attributes to in order to provide exports.  This would increase the
parallelism between objects and modules.  The scope chain from global
to local would be:

 * builtins object
 * module scope
 * the self module
 * an anonymous function block scope

I agree that the builtins object should not be the global window
object that we all know and love.  It should be a frozen capability
object containing JavaScript primitives that can be expected and
conveniently accessed in any programming environment: frozen versions
of String, Number, Object, (is a Map still in?) c.  Perhaps the
browser can host a window module that we explicitly import.  I think
it is also reasonable for this scope to contain some additional
primitives including log or print (since we no longer have to
avoid colliding with window.print).

The module scope, essentially analogous to IMPORTS__ in Caja, should
contain the require function (if this function needs to be unique
for each module, since in a lambda-based implementation it would need
to implicitly be aware of the URL on which the module resides for
module-relative require calls).  It could also contain any imported
names from an from module import * style import.  This would permit
module code to retrieve these values and would also prevent malicious
modules from overwriting the client module's inner-workings.  However,
this might not be a good solution for two remaining concerns: for
security, it would not prevent a malicious module from overwriting
names imported from those modules imported before it; for
verifiability, it would make it more difficult to construct
compile-time checks for name errors.  In this respect, I recognize a
tension and am resigned to the final value judgement.

The module scope could also contain a module variable that refers to
the current module, plus moduleScope, and builtins as deemed fit.
Also, the moduleUrl, like __FILE__ would be handy for
introspection.

The module itself could be in the scope chain.  This would permit
programmers to reference provided functions without explicating this
or module.

And, naturally, there would need to be an empty anonymous scope chain
for private closure variables for the module.

That's the kind of environment I believe JavaScript should wrap around
modules when they're loaded.  I think it's also important that
module's be singleton by virtue of memoizing the ultimate require
function.  I say ultimate because this would be the function that
requires a module from it's fully qualified URL.  Which leads me to my
thoughts about the require function's calling conventions.

I believe that the require function should be a continuation, either
implicit or explicit, that yields and blocks until the module has been
loaded, or accepts a continuation as an optional argument.  I also
think that module's should be identified and loaded with URL's.  There
should be a notion of a module root, a base URL for script paths.  I
do not think that we should not support anything like a lookup chain
of PATHs, since this would incur major performance problems as the
user agent looks and fails to find modules in each successive PATH.
There should be one, and it should be global, determined by the user
agent, perhaps deferring to a script path defined somewhere in the
HTML for browser agents.  There should also be module relative paths.
This would liberate module's from the names of the directories and
domains that contain them, increasing reuse.

The require function might also benefit from accepting a version
number, although I think it would suffice to explicate that in the URL

Re: Remarks about module import

2008-08-23 Thread Kris Kowal
Peter,

 Can you provide concrete examples (something a few lines longer than a
 hello world module) which shows both the module and importer code?

sink.js

/**
this module provides a `sink` function which allows the
user to cause a DOM element to forward its events to
one and only one, detachable Widget object that implements
`./event.js#Signaler`.
*/

/* these are modules by the same author, in the same directory */
from ./urllib.js import urlJoin;
from ./base.js import Set;
/* this is a cross-browser compatibility layer */
from ./browser.js import normalizeEventName, browserEventName;
/* presumably browser is a module provided by the browser in some
 * cross-browser compatible way. */
from chrome://js/browser.js import observe;

/* using let or var makes a variable private to the module */
let widgetNs = urlJoin(__FILE__, '#widget'); // or
let widgetNs = urlJoin(moduleUrl, '#widget');
let sinksAttribute = urlJoin(__file__, '#sinks');
/* the name __FILE__, moduleUrl, __file__, or __DIR__
 * isn't as important as the behavior.  It would not
 * be onerous to provide both module file and dir variables,
 * but dir can be inferred from file and is best
 * dealt with via urlJoin which handles both cases unless
 * the provider of __DIR__ is unscrupulous about the
 * final forward-slash. */

/* assigning to this makes it an export */
this.sink = function (element, widget, eventName) {
if (element[widgetNs]  element[widgetNs] != widget) {
element[widgetNs].final();
}
element[widgetNs] = widget;
let sinks = element.getAttribute(sinksAttribute);
element[sinksNs] = sinks;

let normalizedEventName = normalizeEventName(eventName);
let browserEventName = browserEventName(eventName);

if (!sinks.has(normalizedEventName)) {
observe(element, browserEventName, function () {
let widget = this.target[widgetNs];
widget.signal(normalizedEventName, this);
});
sinks.insert(normalizedEventName);
}

/* break reference cycles */
widget = undefined;
element = undefined;
};


index.js

from ./sink.js import sink; // or
let sink = require(./sink.js).sink;
from http://jquery.com/dist/jQuery.10.1.js; import jQuery as $
from ./my-widget.js import MyWidget
sink($('#widget'), MyWidget());


Kris Kowal
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-19 Thread Ingvar von Schoultz
[EMAIL PROTECTED] wrote:
 An importer could use this as follows --
 
   var doc = ...;
   var bg = ...;
 
   import
   of fetchModule('http://foo.com/someModule.js'),
   with document: doc, background: bg
   using t: toggle, s: set;

 From the descriptions it looks like this could instead use
a syntax based on destructuring assignment, if es-harmony
will have destructuring:

 var {toggle: t, set: s} = import
 (   fetchModule ('http://foo.com/someModule.js'),
 {document: doc, background: bg}
 );
 t();

One advantage would be that people would remember this syntax
easily, since it's useful elsewhere.

As a side effect, one could then choose to use the returned
object instead:

 var m = import
 (   fetchModule ('http://foo.com/someModule.js'),
 {document: doc, background: bg}
 );
 m.toggle();

-- 
Ingvar von Schoultz

___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-19 Thread Mark S. Miller
On Tue, Aug 19, 2008 at 1:00 AM, Ingvar von Schoultz
[EMAIL PROTECTED] wrote:
  From the descriptions it looks like this could instead use
 a syntax based on destructuring assignment, if es-harmony
 will have destructuring:

I expect es-harmony to have destructuring bind.



 var {toggle: t, set: s} = import
 (   fetchModule ('http://foo.com/someModule.js'),
 {document: doc, background: bg}
 );
 t();

 One advantage would be that people would remember this syntax
 easily, since it's useful elsewhere.

 As a side effect, one could then choose to use the returned
 object instead:

 var m = import
 (   fetchModule ('http://foo.com/someModule.js'),
 {document: doc, background: bg}
 );
 m.toggle();


Good suggestions! I like it.


-- 
 Cheers,
 --MarkM
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-19 Thread ihab . awad
 Also I strongly agree that a module should *not* implicitly capture
 the lexical scope in which it is imported.
 I don't think anyone proposed any such thing. Do you?
 Ihab's post said: ...

Apologies if I caused confusion here -- I was merely trying to state
strongly a conceptual desideratum regardless of whether or not it was
proposed. Cheers,

Ihab

-- 
Ihab A.B. Awad, Palo Alto, CA
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-18 Thread ihab . awad
On Mon, Aug 18, 2008 at 4:46 PM, Brendan Eich [EMAIL PROTECTED] wrote:
 On Aug 18, 2008, at 1:44 PM, [EMAIL PROTECTED] wrote:
  whether modules should be like ES1-3's weak notion of program units
 or should be something new: purely lexical scope containers.

I was making a weak reference ;) to the ES3 Program but picking and
choosing. Plus my head is deep in the Caja world. Apologies for the
lack of clarity.

My proposal is the latter per your question: A module is an isolated
lexical scope container, and contains no implicit references to any
shared global object.

 This reasoning seems backwards. If modules are added in a first-class way to
 the JS, they present an opportunity to avoid the global objec utterly, and
 enforce true lexical scope. Since the Program nonterminal from ES1-3 is
 evaluated using a shared global object in browser embeddings, it cannot be
 restated using this lexical-scope-only idea of a module.

Right, so yes, I agree entirely.

 Inside a module, introduced by some kind of explicit syntax, only lexical
 scope is allowed. No global properties are available. Typos in unqualified
 identifier expressions can be caught at compile time. Cats and dogs live
 together in peace ;-).

Yup, live they do. :) That said, we in Caja land have worried about
whether *some* default global properties should be made available --
objects that are essentially powerless like Function and Number, and
which would be a pain in the neck to have to explicitly pass down to
subordinate modules every time with every importModule statement.
What this set of defaults would or should be is up in the air, mainly
because Date would logically be one of them yet it is notably *not*
powerless.

Thanks!!

Ihab

-- 
Ihab A.B. Awad, Palo Alto, CA
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-18 Thread Brendan Eich
On Aug 18, 2008, at 4:55 PM, David-Sarah Hopwood wrote:

 I really like the general approach and the simplicity of Ihab's  
 proposal.
 Also I strongly agree that a module should *not* implicitly capture
 the lexical scope in which it is imported.

I don't think anyone proposed any such thing. Do you?


 I'm not sure why 'provide' needs new syntax, though.

Syntax is (a) often good UI; (b) special form expression where  
there's no library way to say what the special form says.

Why should everything be lambda-coded?

What if I change your bindings for module and provide? (Maybe I  
can't; please explain why not.)

I'm not being snarky (or not merely ;-). The pre-Harmony extreme of  
no new syntax, ever is dead. Asking whether new syntax pays for  
itself is ok, but the question becomes vacuous when the only  
demonstration against new syntax begs questions about usability and  
integrity.

/be


___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-18 Thread ihab . awad
On Mon, Aug 18, 2008 at 5:17 PM, Brendan Eich [EMAIL PROTECTED] wrote:
 On Aug 18, 2008, at 5:02 PM, [EMAIL PROTECTED] wrote:
 That said, we in Caja land have worried about
 whether *some* default global properties should be made available --

 Why couldn't they be imported from a standard module? Must everything be
 passed down? Maybe in Caja, but I don't see that as a requirement on
 successor ES standards.

Even in Caja, it's possible for one module to import another. What
needs to be passed down is *authority*, not the ability to execute
code.

But ok, yes, if people like the idea of using an importModule
construct to get the Function and Number objects, say, then sure,
that's a great solution.

What it means essentially is that the importModule construct, plus
some fetchModule service that knows where to find the primordial
objects, together constitute the material provided to a module by
default. If this can be made to work cleanly while allowing
user-supplied fetchModule implementations that get module code from
(say) a database or whatever, then that's peachy.

Ihab

-- 
Ihab A.B. Awad, Palo Alto, CA
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-18 Thread ihab . awad
Fwiw --

On Mon, Aug 18, 2008 at 5:13 PM, Brendan Eich [EMAIL PROTECTED] wrote:
 On Aug 18, 2008, at 4:55 PM, David-Sarah Hopwood wrote:
 I'm not sure why 'provide' needs new syntax, though.

 Syntax is (a) often good UI; (b) special form expression where
 there's no library way to say what the special form says.

In my proposal, what I'm calling importModule needs to be a special
form if it is to be able to insert bindings into the lexical scope in
which it is called. Everything else can be done with just plain old
function calls. Whether or not it *should* is a whole 'nother ball of
wax of a different color.

 What if I change your bindings for module and provide? (Maybe I
 can't; please explain why not.)

Any given instantiation of a module is always vulnerable in diverse
and sundry ways to its importer. Whether my importer changed my
bindings for the module loading mechanism is the least of my worries
if I'm importing all the rest of my channels to the outside world from
it.

Ihab

-- 
Ihab A.B. Awad, Palo Alto, CA
___
Es-discuss mailing list
Es-discuss@mozilla.org
https://mail.mozilla.org/listinfo/es-discuss


Re: Remarks about module import

2008-08-18 Thread ihab . awad
On Mon, Aug 18, 2008 at 5:59 PM, Brendan Eich [EMAIL PROTECTED] wrote:
 On Aug 18, 2008, at 5:25 PM, [EMAIL PROTECTED] wrote:
 Even in Caja, it's possible for one module to import another. What
 needs to be passed down is *authority*, not the ability to execute
 code.

 I was asking, I'm happy with an answer. But what's the requirement,
 exactly? Can you give an example?

I'll back into this topic, in a way. From MarkM's thesis, page 77,
caption to figure 8.2 --

  Authority is the Ability to Cause Effects. If 1) Bob has permission to talk
  to Alice, 2) Alice has permission to write /etc/passwd, and 3) Alice chooses
  to write there any text Bob asks her to, then Bob has authority to write
  /etc/passwd.

Loading a module in itself *may* cause effects (e.g., if the code is
retrieved via HTTP). Otherwise, by executing this code, the entity
importing the module may only consume memory and CPU time; it gains no
new authority that it did not have before. (And, strictly speaking,
the authority to load code should properly be granted by the importer
of a module.)

This requirement is driven by the desire to eliminate *ambient*
authority: a piece of code should not have abilities to cause effects
that have not been explicitly granted to it. For example, in the Unix
example, any process has the ambient authority to read a large subset
of the files on the system, regardless of whether these are needed for
the task at hand. To quote a classic example, when I write:

  cp x.txt y.txt

the cp process can attempt to read /etc/passwd and, if successful,
open a socket and send the contents to the evil.com server. Yet it
needed only to read x.txt and write y.txt and, were it so
confined, the damage it could cause would be limited to corrupting the
contents of y.txt. This damage is consistent with a simple causal
model: cp can only damage the things I tell it to work on, and
nothing else. And finally, such damage, being narrowly constrained, is
now such that there is practically no reasonable economic or other
incentive for authoring a malicious cp.

From MarkM's thesis, page 16:

  The Principle of Least Authority (POLA) recommends that you
  grant each program only the authority it needs to do its job [MS03].

and this, as I hopefully motivated, is why we need to be sure that a
module gets authority only explicitly, from its invoker.

A capability is just an object reference that conveys authority.
Typically, it is an object that, directly or transitively, can cause
effects such as modifying valuable data held by some module; making
changes to stable storage; displaying information on an output device;
reading an input device; using the network; etc.

A deep vision of capability systems would be that, on a computer
system, the ability to cause effects at a primitive level --
essentially, access to hardware devices -- is owned by some powerful
module instances which attenuate that into fine-grained objects, each
of which represents some reasonable chunk (e.g., creating a connection
to a specific host, or writing to a specific rectangle of the screen,
or communicating in read-only fashion with a specific USB mass storage
device). Careful interaction between modules in the system, keeping
POLA in mind, ensures that everyone gets just the authority they need.

The wiring of capabilities can be done by module configuration, but an
important source of wiring information is the end-user. A deep
capability system exposes to the end-user the ability to divvy up
their authority between the modules to which they have access. For
example, given a stock tracking gadget module, I may create two
instances: one to hold my private information about what stocks I own,
and another that just displays some information I consider
interesting. The first I keep to myself, but I publish the second on
my public profile page. Importantly, the fact that these are two
instances of the same code does not grant them the ability to
communicate; since I have not wired up my private instance to anything
in my public profile, I know that my data is safe.

In fact, the classic rewriting of the cp example is to simply pass
it file descriptors, rather than file names:

  cp  x.txt  y.txt

Thus redefined, cp needs no ambient access to any files; everything
it needs is in its arguments or its Unix file descriptors, and that is
all provided by its parent process. POLA is satisfied. (The fact that
pretty much all Unices give cp the ambient authority to do pretty
much anything else, even under these circumstances, is, if one is to
take a polemical ocap perspective, simply a bug.)

 I thought you suggested that a few built-ins (Function, Number, not Date)
 were safe to populate in a global scope, above a module's apparent top
 lexical scope. A safe (immutable, I hope) top-level. Do I have that right?

Yes, that was my suggestion.

 Your post asserted that responsibility for naming a module belongs to the
 importer (requirer? ugh). That could be the whole truth,