Skip to content
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

Subset of intrinsics in a synthetic Realm #288

Closed
leobalter opened this issue Jan 7, 2021 · 12 comments
Closed

Subset of intrinsics in a synthetic Realm #288

leobalter opened this issue Jan 7, 2021 · 12 comments

Comments

@leobalter
Copy link
Member

leobalter commented Jan 7, 2021

I tried to categorize the global names and intrinsics available in ECMAScript and give some sense of what we need for the language syntax to work properly from what seems to be API only.

Group 1

These are intrinsics we can't remove without compromising the syntax.

Among with the given intrinsics, we have some global names without a respective intrinsic.

Please notice the objects are including their properties regularly, e.g. Object includes Object.fromEntries, etc.. I'm avoiding the complexity of delivering incomplete objects for now.

Intrinsic Name Global Name
%AggregateError% AggregateError
%Array% Array
%ArrayIteratorPrototype%  
%AsyncFromSyncIteratorPrototype%  
%AsyncFunction%  
%AsyncGeneratorFunction%  
%AsyncIteratorPrototype%  
%BigInt% BigInt
%Boolean% Boolean
%Error% Error
%eval% eval
%EvalError% EvalError
%ForInIteratorPrototype%  
%Function% Function
%GeneratorFunction%  
%IteratorPrototype%  
%Number% Number
%Object% Object
%Promise% Promise
%RangeError% RangeError
%ReferenceError% ReferenceError
%RegExp% RegExp
%RegExpStringIteratorPrototype%  
%String% String
%StringIteratorPrototype%  
%Symbol% Symbol
%SyntaxError% SyntaxError
%ThrowTypeError%  
%TypeError% TypeError
globalThis
Infinity
NaN
undefined

Group 2

No syntax required, but big functionality compromise.

Those are mostly the TypedArrays group. I've seen a pushback against not having those available as the implementation functionality is compromised without a native usage.

Intrinsic Name Global Name
%ArrayBuffer% ArrayBuffer
%BigInt64Array% BigInt64Array
%BigUint64Array% BigUint64Array
%DataView% DataView
%Float32Array% Float32Array
%Float64Array% Float64Array
%Int8Array% Int8Array
%Int16Array% Int16Array
%Int32Array% Int32Array
%TypedArray%  
%Uint8Array% Uint8Array
%Uint8ClampedArray% Uint8ClampedArray
%Uint16Array% Uint16Array
%Uint32Array% Uint32Array

Group 3

This subset has a mix of classic names (Date, JSON, Math) and some names that might be relatively compromised without being native.

There is a mixed feeling about the names in group, but their absence could be handled in user land without compromise to the syntax.

Intrinsic Name Global Name
%Date% Date
%JSON% JSON
%Map% Map
%MapIteratorPrototype%  
%SetIteratorPrototype%  
%Math% Math
%Set% Set
%SetIteratorPrototype%  
%WeakMap% WeakMap
%WeakSet% WeakSet

Group 4

This subset is interesting. You won't have a syntax issue but some of these are limited. Although, this limitation is similar to other non ES parts as Workers, available in browsers, Node, and XS.

I'm biased to have apis like SharedArrayBuffer and WeakRef here and not on group 2.

Intrinsic Name Global Name
%Atomics% Atomics
%decodeURI% decodeURI
%decodeURIComponent% decodeURIComponent
%encodeURI% encodeURI
%encodeURIComponent% encodeURIComponent
%FinalizationRegistry% FinalizationRegistry
%isFinite% isFinite
%isNaN% isNaN
%parseFloat% parseFloat
%parseInt% parseInt
%Proxy% Proxy
%Reflect% Reflect
%SharedArrayBuffer% SharedArrayBuffer
%URIError% URIError
%WeakRef% WeakRef

Given this, I wonder if there is a way to work through some issues raised like in #284 and #262.

The idea is to find a good subset that won't break API and could still benefit of enough virtualization if necessary.

@ljharb
Copy link
Member

ljharb commented Jan 7, 2021

Map and Set's O(1) access for object keys is not polyfillable, nor is anything "Weak", so i think all 4 of those (and their related iterator intrinsics) belongs in Group 2.

Proxy and WeakRef are also not polyfillable.

@leobalter
Copy link
Member Author

polyfillable in a synthetic Realm is a quite bizarre point here. Like I mentioned for Workers, you can't really reproduce their behavior, but you would still be able to virtualize the synthetic Realm if the incubator does have access to its globals.

The groups represent some of my (biased) vision over high impact. We can change this.

The concern we are trying to address is the feedback to avoid the distinction from what is ES and other Standards, like those from the Web environment. It's hard to present a list where everyone will be satisfied. I'd be happy to start trying out a minimum set knowing it's easy for us to expand during an eventual experimental phase (stage 3)

@leobalter
Copy link
Member Author

cc @annevk I'd like to get your feedback here, please.

@ljharb
Copy link
Member

ljharb commented Jan 7, 2021

I'm looking at it from the perspective of untrusted user code that wants these features but needs to be able to operate in a synthetic realm. Everything that's not provided by default is something the application developer has to know to polyfill, and has to polyfill correctly, so that the untrusted user code can function properly.

@leobalter
Copy link
Member Author

We diverge opinions of usage of untrusted code, but everything not limited to ES are things that need the application to provide or understand that any code running in a synthetic Realm will need or can use.

"Knowing how to polyfill" needs context for Realms, in fact the person using synthetic Realms need to know how to virtualize and provide APIs an application would use. In my example I used Workers, an API that is broadly available in different realities (browser, node, and XS). The lack of it if similar to WeakMap, WeakSet, etc.

@ljharb
Copy link
Member

ljharb commented Jan 7, 2021

Indeed, that's true. What I would expect both requires the least effort and is the most likely to be done correctly on behalf of application devs, and untrusted code authors, is if a base Realm was available for universal code, a subclassed WebRealm and NodeRealm for those environments, etc. I don't personally see any value in forcing everyone to pretend the web is the only environment, nor forcing everyone to pretend that cross-environment code doesn't exist, nor in pretending that JS devs don't actually know the difference (they typically do, in my experience).

@annevk
Copy link
Member

annevk commented Jan 8, 2021

I suspect what you want to do is develop a set of principles as this will undoubtedly come up for future features as well.

@bathos
Copy link
Contributor

bathos commented Jan 8, 2021

As someone who was hoping to make use of the realms proposal, I’d never expected these ES intrinsics would be absent. This would likely mean we’d stick with current iframe solutions.

@leobalter
Copy link
Member Author

@annevk that's what I'm trying to learn here. From my understanding, there is a feeling that most of TC39 is ok with the current intrinsics and global names present in ECMAScript.

I believe there would be pushback on any subset we create and the complexity budget we'd need to add to ECMAScript, distinguishing intrinsics wouldn't be welcomed.

I'm bringing this topic for discussion in the next plenary. I'm still trying to create a better perspective on how we could do this, and the effects of it.

I don't personally see any value in forcing everyone to pretend the web is the only environment, nor forcing everyone to pretend that cross-environment code doesn't exist, nor in pretending that JS devs don't actually know the difference (they typically do, in my experience).

I agree with @ljharb here, but willing to take more feedback if we should limit the names in a synthetic Realm.

@bathos
Copy link
Contributor

bathos commented Jan 9, 2021

I realized it might be worth describing our use case a bit since I think it may be pretty different from the primary motivating cases.

Rather than using an iframe for isolation of untrusted code, we use it in library code that aims to minimize sensitivity to poisoned intrinsic or platform objects of the host realm. This is a robustness measure, not a security measure; it requires initial assumptions about the environment which aren’t guaranteed. However this set of assumptions is a very tiny fraction of the assumptions normally made.

Capturing references at initial eval is not always sufficient due to, for example, @@species-sensitive constructors and RegExp’s API design. Mitigation strategies for these cases can be very painful unless we actually evaluate most of the code in a (presumed) private realm where things like array literal syntax and spread can be used without additional guards. Even where capturing references in the host realm is sufficient, it tends to imply writing “weird” code (wmSet(wm, key, val), not wm.set(key, val)), etc.).

The realms proposal seems to provide better mechanisms for this than iframes. While it’s possible to close over the content window of an iframe by connecting the iframe in a closed shadow root, it remains possible for any other code in the host realm to abruptly cause its disconnection via an ancestor node of the shadow’s host. This breaks all task scheduling within the now-disconnected window, including Promise reactions (and therefore async functions). These failures are abrupt and most are silent. There are additional disconnection effects which are inconsistent between browsers.

This is why I’d have hoped for the full set of ES intrinsics here (even if opt-in) — it’d be like, the whole point for us :)

@bedney
Copy link

bedney commented Jan 18, 2021

Sorry if I'm adding noise here, but I want to agree very strongly with @bathos comment. Our primary use-case for Realms is exactly his use case - isolation of poisoned intrinsics (and, as he points out, not for security - but for robustness).

@leobalter
Copy link
Member Author

I'm decided to not pursue with any subset of ES intrinsics for the Realms globals. Thanks everyone for the feedback and insights!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

5 participants