'use strict';

if (self.importScripts) {
  self.importScripts('/resources/testharness.js');
}

// 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;
  }
}

for (const func of ['WritableStreamDefaultController', 'WritableStreamDefaultWriter']) {
  test(() => {
    assert_equals(self[func], undefined, `${func} should not be defined`);
  }, `${func} should not be exported on the global object`);
}

// Now get hold of the symbols so we can test their properties.
self.WritableStreamDefaultController = (() => {
  let controller;
  new WritableStream({
    start(c) {
      controller = c;
    }
  });
  return controller.constructor;
})();
self.WritableStreamDefaultWriter = new WritableStream().getWriter().constructor;

const expected = {
  WritableStream: {
    constructor: {
      type: 'constructor',
      length: 0
    },
    locked: {
      type: 'getter'
    },
    abort: {
      type: 'method',
      length: 1
    },
    getWriter: {
      type: 'method',
      length: 0
    }
  },
  WritableStreamDefaultController: {
    constructor: {
      type: 'constructor',
      length: 4
    },
    error: {
      type: 'method',
      length: 1
    }
  },
  WritableStreamDefaultWriter: {
    constructor: {
      type: 'constructor',
      length: 1
    },
    closed: {
      type: 'getter'
    },
    desiredSize: {
      type: 'getter'
    },
    ready: {
      type: 'getter'
    },
    abort: {
      type: 'method',
      length: 1
    },
    close: {
      type: 'method',
      length: 0
    },
    releaseLock: {
      type: 'method',
      length: 0
    },
    write: {
      type: 'method',
      length: 1
    }
  }
};

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`);
          } else {
            assert_false(IsConstructor(prototype[name]), `${name} should not be a constructor`);
          }
        }, `${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 sinkMethods = {
  start: {
    length: 1,
    trigger: () => {}
  },
  write: {
    length: 2,
    trigger: writer => writer.write()
  },
  close: {
    length: 0,
    trigger: writer => writer.close()
  },
  abort: {
    length: 1,
    trigger: writer => writer.abort()
  }
};

for (const method in sinkMethods) {
  const { length, trigger } = sinkMethods[method];

  // Some semantic tests of how sink 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 ws = new WritableStream({
      [method](...args) {
        argCount = args.length;
      }
    });
    return Promise.resolve(trigger(ws.getWriter())).then(() => {
      assert_equals(argCount, length, `${method} should be called with ${length} arguments`);
    });
  }, `sink method ${method} should be called with the right number of arguments`);

  promise_test(() => {
    let methodWasCalled = false;
    function Sink() {}
    Sink.prototype = {
      [method]() {
        methodWasCalled = true;
      }
    };
    const ws = new WritableStream(new Sink());
    return Promise.resolve(trigger(ws.getWriter())).then(() => {
      assert_true(methodWasCalled, `${method} should be called`);
    });
  }, `sink method ${method} should be called even when it's located on the prototype chain`);

  if (method !== 'start') {
    promise_test(t => {
      const unreachedTraps = ['getPrototypeOf', 'setPrototypeOf', 'isExtensible', 'preventExtensions',
                              'getOwnPropertyDescriptor', 'defineProperty', 'has', 'set', 'deleteProperty', 'ownKeys',
                              'apply', 'construct'];
      const handler = {
        get: t.step_func((target, property) => {
          if (property === 'type') {
            return undefined;
          }
          assert_in_array(property, ['start', method], `only start() and ${method}() should be called`);
          return () => Promise.resolve();
        })
      };
      for (const trap of unreachedTraps) {
        handler[trap] = t.unreached_func(`${trap} should not be trapped`);
      }
      const sink = new Proxy({}, handler);
      const ws = new WritableStream(sink);
      return trigger(ws.getWriter());
    }, `unexpected properties should not be accessed when calling sink method ${method}`);
  }
}

done();
