-
Notifications
You must be signed in to change notification settings - Fork 25
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Split or unified namespaces? #14
Comments
My current feeling is that the web + JS should use a single namespace, but other environments like Node.js might use additional namespaces for Node-specific functionality. |
I think that the Web should just be an environment where JS is used, and it should not be treated special in regard to namespaces. I think everything that is web-specific (web standards) should be namespaced. |
I'm trying to wrap my mind around this. I think it makes sense for Node.js but I'm not sure how it would work for other environments. Here's my best guess: import { Promise, Worker, Atomics, ArrayBuffer } from '@std/common';
import { document, window, DocumentFragment } from '@std/dom';
import { writeFile, readFile } from '@nodejs/fs';
import cluster from '@nodejs/cluster';
import { app, BrowserWindow } from '@electron/common';
import desktopCapturer from '@electron/desktopCapturer'; Is Electron an environment or should it stick to user-land modules? |
I don't think there's any particularly reasonable slicing of things for the web platform to use separate namespaces, so it should all be on one namespace. (Plus, in general, separate namespaces means I'll have to remember two names for each API - the actual name, and the namespace that is arbitrarily associated with it. |
That's not a legitimate worry unless you have an example of a module that would be warranted in two different scopes. If you know what you are importing the scope is obvious. |
|
I think that's off topic but in this case Id just mirror it on the other scope. |
@ljharb In the case of import { Promise, Worker, Atomics, ArrayBuffer } from '@std/common';
import { document, window, DocumentFragment } from '@std/dom';
import { URL, fetch } from '@std/net'; |
@styfle I think that's why having things be split isn't a good idea - if there's only a single namespace, then the user doesn't have to guess about what category the thing they want is in - they just import it, and if it's not there, it'll error out prior to evaluation. |
I think having multiple namespaces is fundamental for the ecosystem is governance and standardization. Who owns/organizes the non-prefixed namespace? Who owns/organizes the std namespace? I think this is far more important than the actual syntax. If it becomes a recommended pattern that a runtime/platform can implement/add its own runtime specific part of the std lib, then it negates the benefits of having a std library in the first place. If the goal for the standard library is to include browser specific APIs, then it would be a huge loss for the ecosystem for non-browser JS implementations. I think the only solution is to have multiple namespaces, so it’s clear for the user what that API is about. It also makes polyfills easier, because it’d be clear where there are tradeoffs. Let me make an example: having URL in the standard library would be a great win as it’s a simple data structure. Having fetch would become problematic for non-browser environments, mainly because fetch has some defined semantics regarding caching, security and connection management that make sense only if the JS vm is associated with a single user. I don’t think having multiple namespaces would be a huge problem for the community: people need to read the docs anyway and most editors offers great autocomplete. |
I lean towards a shared namespace but to make an educated guess Id need at least the first 10 or so modules that will be available once std is implemented. If you are planning on organic additions, that might clash with the chosen approach if the eventual modules are not the ones expected. In that regard, Id recommend to go with the unified approach as the desired outcome and if it fails, allow/enable the split if it's really warranted. TL;DR: your first goal should be to make std worth using and design it as a template to enable the possibility of other environment-specific scopes. |
I think the issue of how to manage the shared namespace could become more significant if we increase the velocity of what we standardize, which I hope this effort will enable. However, I agree with many points made here about the benefits of a shared namespace. We've also been using names which are less likely to overlap--in web standards, it's often a single additional global whose name starts with something like So far, the governance of the shared global object namespace has been implicitly based on browsers: any overlaps get noticed in their development process by the time they're looking into implementing and shipping something, if not before. So far, this has worked just fine, but it's worked in an environment with less potential contention by design than we might have in the future. Do we want to continue this browser-based namespace governance, or should we do something more explicit to coordinate between standards bodies to identify potential conflicts earlier in the design process? I'm optimistic that we can cooperate here. To the people who want split namespaces: What challenges do you see in cooperating here? |
The current global namespace recommends every runtime to add its own things to it, meaning that there is no single source of truth to what you can expect being global in a JS environment. The benefit of a standard library is that it is ubiquitous. If every different JS environment can add to the standard library things that could not be implemented by a generic JS runtime (they are specific to a browser or a server for example), i.e. if pieces of the standard library become optional, then the benefit of having a standard library collapses for an ergonomic point of view when creating isomorphic code. Multiple namespaces enable the web to standardize all the APIs that make sense in a Browser context and at the same time it enables non-Browser environments to not do so. As an example, the DOM could be standard, and there will no question for an IoT runtime to have the DOM or not. I think the standard namespace should be limited to utilities of the core part of the language and do not assume where something could be run. Would you expect the engines to include full HTTP/HTTP2/HTTP3 capability, a database, a caching layer, a file system API? I think the greatest thing about JS that enabled so much creativity and innovation was that none of those things where specified. |
I don't see what that has to do with shared/split namespaces. What if we list the pieces of the standard library that are required in the JS spec, and make sure to document what interfaces are supported in what environments carefully, e.g., in MDN? |
That could potentially work, but it would create a lot of confusion on why a certain module is not in a given runtime as it will be buried at the end of a MDN page. There are JS standards and Web standards, this difference is important to developers and they should be immediately aware of it. Moreover creating a namespace mechanism enables runtimes to add custom or experimental behavior in a safe way without any potential collisions. I think adding a standard library is the perfect moment to reduce the friction when writing isomorphic applications. If a developer needs to look at the bottom of an MDN page to know where that part of the standard library work, then this mechanism is only slightly better than adding globals. |
Looking at https://github.com/denoland/deno_std I think @ry might have an opinion on the matter. |
I'm totally in support of reducing the friction when writing isomorphic applications. I don't think sprinkling prefixes throughout JS source implying, "things defined outside of TC39 are not available for isomorphic code" is the best way to do that, since it's already not true. |
I think @mcollina is making some good points, and perhaps I can add to it with a concrete example. Certainly we want to import temporal (a language-level/isomorphic builtin) like so: import { ZonedInstant } from 'std:temporal'; Good so far. From a strictly web/browser point of view, it does make sense to share the namespace: import { asyncLocalStorage } from 'std:async-local-storage'; OK, that seems fine. But if we extend that methodology to Node: import { readFile } from 'std:fs'; That just doesn't look right at all! It feels much more appropriate to have something similar to: import { readFile } from 'node:fs'; Taken together, the situation appears to be that we have priveledged the web and browsers over Node. Is that a good thing? |
Why does it make sense to you to put localStorage in the standard namespace, but not fs? To me that seems like implicit browser bias - I think it either makes sense for neither to do so, or both - iow, both being in the standard namespace "look right" to me. |
As both JS and the Web Platform are based on specced standards, and Node not necessarily - I guess that is fine |
Thanks for posting this. I had not been paying attention to this thread, so I don't know the particular issue yet (will read). But on the general issue stated here, I think it would be terrible for us to privilege the browser/web over Node, or over any of the increasing number of other host environments (IoT, blockchain, ...) |
Just dipping in, but the problem with 'std:async-local-storage' is: which standard? Say Node were standardized. 'std:fs' would still be wrong. You folks are all too acclimated to the web. To those of us focused on other uses of js, 'std:async-local-storage' is just as wrong. |
@erights I think the idea with a standard library is low level apis that for sure exist in all environments. Similar to what already exists, but not all bundled in the global context |
i don't see anything wrong with prioritizing web use-case, as it reflects industry reality. pretty much all javascript software-development in industry deals with (or is ultimately meant to support) passing workflow-data to/from web. |
That’s simply not the case any more, even if it may have been at one time. |
That is nowhere even close to true. |
A thing that would help here is taking |
I would prefer splited namespace because I expect proprietary JavaScript embedding to expose some of their functionalities using modules within a non standard prefix. If we do share the same prefix we could end up with collisions and incompatible APIs. |
Should built-in modules be all with one scope/scheme prefix in their module specifier, or should we have multiple prefixes based on what kind of module they are? I've heard different opinions from different people, so I though it could be good to collect the arguments all in one thread.
Shared namespace
We could put all built-in modules with a specifier like
"@std/module"
or"std:module"
, regardless of where they come from or what they're for.Advantages:
Split namespace
Several different namespaces for built-in modules could be used, such as
"@js/"
,"@html/"
,"@nodejs/"
(or,"js:"
,"html:"
,"nodejs:"
), for different modules.Advantages:
Next steps
What are your thoughts?
The text was updated successfully, but these errors were encountered: