tc39 / test262

Official ECMAScript Conformance Test Suite
Other
2.33k stars 460 forks source link

Tests for exotic global objects #538

Open jugglinmike opened 8 years ago

jugglinmike commented 8 years ago

ES2015 accounts for abrupt completions returned by every call to the global object's essential internal methods. For example, from HasRestrictedGlobalProperty:

  1. Let existingProp be globalObject.[GetOwnProperty].
  2. ReturnIfAbrupt(existingProp).

This is because the global object may be an exotic object, as specified by the first step of InitializeHostDefinedRealm:

  1. If this implementation requires use of an exotic object to serve as realm's global object, let global be such an object created in an implementation defined manner. Otherwise, let global be undefined indicating that an ordinary object should be created as the global object.

Test262 should assert correct behavior for such exotic global objects. This will require a new "helper" function such as $CREATE_REALM(globalObject). Similar to print, hosts would be required to provide an implementation prior to test execution.

But taking a step back, I'm having trouble thinking of a use case for this functionality. My worry is that many (most?) implementers have no need for exotic global objects, and therefore would ignore this aspect of the specification (and any tests for it).

Understanding the use case (and the likelihood of compliance) goes beyond the scope of the specification itself, but that perspective is necessary to properly prioritize test-writing efforts in this area. @bterlson and/or @allenwb: do you have a moment to offer your thoughts on this?

domenic commented 8 years ago

I don't think this is worth testing. In practice implementations only have one kind of global object (or, what I think you would really be testing, global this---they're distinct). The test suites for those objects belong in the implementations, and in any shared test suites they work together on like web-platform-tests, not in test262.

In a 100% coverage world, I guess this is reasonable, but I think it's way down on the priority list.

$CREATE_REALM(globalObject)

More like $CREATE_REALM(globalObject, globalThis). Which, I know from experience working on Node.js's vm module, is not possible with the V8 API---which makes many more assumptions about how globalObject and globalThis relate.

jugglinmike commented 8 years ago

Thanks, Domenic. Separate-but-related concerns include:

The former seems similarly obscure, but the latter seems much more relevant. I also think the latter is more testable--we could get away without realm creation and instead use a host-provided $EVAL_SCRIPT helper.

domenic commented 8 years ago

we could get away without realm creation and instead use a host-provided $EVAL_SCRIPT helper.

How? And why?

jugglinmike commented 8 years ago

I'm thinking of GlobalDeclarationInstantiation.

Object.defineProperty(this, 'foo', {
  value: null,
  enumerable: true,
  writable: true,
  configurable: false
});
$EVAL_SCRIPT('function foo() {}');
assert.sameValue(typeof foo, 'function');

We could use the same pattern to test for behavior of a frozen global object.

domenic commented 8 years ago

Those don't test the behavior of host-defined properties. They test an entirely different part of the spec.

jugglinmike commented 8 years ago

It sounds like I'm misunderstanding something. Here's why I think this is relevant:

GlobalDeclarationInstantiation calls CanDeclareGlobalFunction for each function declaration. If the given name describes a non-configurable property on the global "this" value, CanDeclareGlobalFunction will only return true if the property is also both enumerable and writable.

In order to test this case, Test262 needs to be able to evaluate global code when the global object already has a data property that is {[[Enumerable]]: true, [[Writable]]: true, [[Configurable]]: false}. Since the specification does not define such a property, we would need to create one dynamically and then execute global code.

Admittedly, such a property would not be "host defined"--maybe that is the cause of confusion here. I think for the purposes of the behavior we want to test, though, it would be an acceptable approximation.

domenic commented 8 years ago

Right, all I'm saying is that you're not testing the "In addition" clause from your earlier message.

littledan commented 8 years ago

Even with Proxies as the global object, there are some parts of the spec which would not be observed in current real implementations. Some ECMAScript implementations, such as V8, use a technique called 'snapshotting' where the global object is partially already constructed ahead of time. This forms a sort of 'partial evaluation' of GlobalDeclarationInstantiation--we don't actually call it each time on everything. Although v8::Context::New can accept a global object as a parameter, even if this allowed Proxy (I'm not sure whether it is allowed), that Proxy wouldn't receive all of the defineProperty traps that the spec says.

In general, I wouldn't say that it would be worthless to write tests for GlobalDeclarationInstantiation, but that it's legitimate for an ECMAScript implementation to specialize for certain kinds of global objects, and the global objects that V8 is specialized for all share the property that this behavior is unobservable.

Similarly, if there's a ReturnIfAbrupt in the spec, but all known embedding environments will not throw an exception, it's OK to treat that test as low priority. And the 'missing exotic global object' case falls into the same bucket. I can't think of an embedding environment where this takes place; the web and Node don't seem to be examples.

Note that ECMAScript has specific things in it to allow embedding environments to lock down manipulations of the global object, specifically to prevent the use of Proxies in some important cases for security.

leobalter commented 7 years ago

ping requesting status, is there anything new, @jugglinmike?

jugglinmike commented 7 years ago

No update, Leo. This remains a valid but low-priority coverage issue.