gecko-dev/testing/web-platform/tests/streams/transform-streams/properties.any.js
Jason Orendorff 47519c94b2 Bug 1513570 - Part 1: Adapt stream tests to run in the shell. r=Ms2ger
We don't support byte streams, transform streams, writable streams, or piping
yet, but we will, and in the meantime our own meta files disable those tests
for us.

Differential Revision: https://phabricator.services.mozilla.com/D14314

--HG--
extra : moz-landing-system : lando
2018-12-14 18:14:56 +00:00

189 lines
6.4 KiB
JavaScript

// META: global=worker,jsshell
'use strict';
// The purpose of this file is to test for objects, attributes and arguments that should not exist.
// The test cases are generated from data tables to reduce duplication.
// Courtesy of André Bargull. Source is https://esdiscuss.org/topic/isconstructor#content-11.
function IsConstructor(o) {
try {
new new Proxy(o, { construct: () => ({}) })();
return true;
} catch (e) {
return false;
}
}
test(() => {
assert_equals(self['TransformStreamDefaultController'], undefined,
`TransformStreamDefaultController should not be defined`);
}, `TransformStreamDefaultController should not be exported on the global object`);
// Now get hold of the symbol so we can test its properties.
self.TransformStreamDefaultController = (() => {
let controller;
new TransformStream({
start(c) {
controller = c;
}
});
return controller.constructor;
})();
const expected = {
TransformStream: {
constructor: {
type: 'constructor',
length: 0
},
readable: {
type: 'getter'
},
writable: {
type: 'getter'
}
},
TransformStreamDefaultController: {
constructor: {
type: 'constructor',
length: 0
},
desiredSize: {
type: 'getter'
},
enqueue: {
type: 'method',
length: 1
},
error: {
type: 'method',
length: 1
},
terminate: {
type: 'method',
length: 0
}
}
};
for (const c in expected) {
const properties = expected[c];
const prototype = self[c].prototype;
for (const name in properties) {
const fullName = `${c}.prototype.${name}`;
const descriptor = Object.getOwnPropertyDescriptor(prototype, name);
test(() => {
const { configurable, enumerable } = descriptor;
assert_true(configurable, `${name} should be configurable`);
assert_false(enumerable, `${name} should not be enumerable`);
}, `${fullName} should have standard properties`);
const type = properties[name].type;
switch (type) {
case 'getter':
test(() => {
const { writable, get, set } = descriptor;
assert_equals(writable, undefined, `${name} should not be a data descriptor`);
assert_equals(typeof get, 'function', `${name} should have a getter`);
assert_equals(set, undefined, `${name} should not have a setter`);
}, `${fullName} should be a getter`);
break;
case 'constructor':
case 'method':
test(() => {
assert_true(descriptor.writable, `${name} should be writable`);
assert_equals(typeof prototype[name], 'function', `${name} should be a function`);
assert_equals(prototype[name].length, properties[name].length,
`${name} should take ${properties[name].length} arguments`);
if (type === 'constructor') {
assert_true(IsConstructor(prototype[name]), `${name} should be a constructor`);
assert_equals(prototype[name].name, c, `${name}.name should be '${c}'`);
} else {
assert_false(IsConstructor(prototype[name]), `${name} should not be a constructor`);
assert_equals(prototype[name].name, name, `${name}.name should be '${name}`);
}
}, `${fullName} should be a ${type}`);
break;
}
}
test(() => {
const expectedPropertyNames = Object.keys(properties).sort();
const actualPropertyNames = Object.getOwnPropertyNames(prototype).sort();
assert_array_equals(actualPropertyNames, expectedPropertyNames,
`${c} properties should match expected properties`);
}, `${c}.prototype should have exactly the expected properties`);
}
const transformerMethods = {
start: {
length: 1,
trigger: () => Promise.resolve()
},
transform: {
length: 2,
trigger: ts => ts.writable.getWriter().write()
},
flush: {
length: 1,
trigger: ts => ts.writable.getWriter().close()
}
};
for (const method in transformerMethods) {
const { length, trigger } = transformerMethods[method];
// Some semantic tests of how transformer methods are called can be found in general.js, as well as in the test files
// specific to each method.
promise_test(() => {
let argCount;
const ts = new TransformStream({
[method](...args) {
argCount = args.length;
}
}, undefined, { highWaterMark: Infinity });
return Promise.resolve(trigger(ts)).then(() => {
assert_equals(argCount, length, `${method} should be called with ${length} arguments`);
});
}, `transformer method ${method} should be called with the right number of arguments`);
promise_test(() => {
let methodWasCalled = false;
function Transformer() {}
Transformer.prototype = {
[method]() {
methodWasCalled = true;
}
};
const ts = new TransformStream(new Transformer(), undefined, { highWaterMark: Infinity });
return Promise.resolve(trigger(ts)).then(() => {
assert_true(methodWasCalled, `${method} should be called`);
});
}, `transformer method ${method} should be called even when it's located on the prototype chain`);
promise_test(t => {
const unreachedTraps = ['getPrototypeOf', 'setPrototypeOf', 'isExtensible', 'preventExtensions',
'getOwnPropertyDescriptor', 'defineProperty', 'has', 'set', 'deleteProperty', 'ownKeys',
'apply', 'construct'];
const touchedProperties = [];
const handler = {
get: t.step_func((target, property) => {
touchedProperties.push(property);
if (property === 'readableType' || property === 'writableType') {
return undefined;
}
return () => Promise.resolve();
})
};
for (const trap of unreachedTraps) {
handler[trap] = t.unreached_func(`${trap} should not be trapped`);
}
const transformer = new Proxy({}, handler);
const ts = new TransformStream(transformer, undefined, { highWaterMark: Infinity });
assert_array_equals(touchedProperties, ['writableType', 'readableType', 'transform', 'flush', 'start'],
'expected properties should be got');
return trigger(ts).then(() => {
assert_array_equals(touchedProperties, ['writableType', 'readableType', 'transform', 'flush', 'start'],
'no properties should be accessed on method call');
});
}, `unexpected properties should not be accessed when calling transformer method ${method}`);
}