diff --git a/files/en-us/web/javascript/reference/errors/bad_super_call/index.md b/files/en-us/web/javascript/reference/errors/bad_super_call/index.md new file mode 100644 index 000000000000000..c13a297c847141a --- /dev/null +++ b/files/en-us/web/javascript/reference/errors/bad_super_call/index.md @@ -0,0 +1,112 @@ +--- +title: "SyntaxError: super() is only valid in derived class constructors" +slug: Web/JavaScript/Reference/Errors/Bad_super_call +page-type: javascript-error +--- + +{{jsSidebar("Errors")}} + +The JavaScript exception "super() is only valid in derived class constructors" occurs when the {{jsxref("Operators/super", "super()")}} call is used somewhere that's not the body of a [constructor](/en-US/docs/Web/JavaScript/Reference/Classes/constructor) in a class with [`extends`](/en-US/docs/Web/JavaScript/Reference/Classes/extends) keyword. + +## Message + +```plain +SyntaxError: 'super' keyword unexpected here (V8-based) +SyntaxError: super() is only valid in derived class constructors (Firefox) +SyntaxError: super is not valid in this context. (Safari) +``` + +## Error type + +{{jsxref("SyntaxError")}} + +## What went wrong? + +The `super()` call is used to invoke the base constructor of a derived class, so the base class can initialize the {{jsxref("Operators/this", "this")}} object. Using it anywhere else doesn't make sense. + +`super()` can also be defined in an arrow function that's nested within the constructor. However, it cannot be defined in any other kind of function. + +## Examples + +### Invalid cases + +You cannot call `super()` if the class has no `extends`, because there's no base class to call: + +```js example-bad +class Base { + constructor() { + super(); + } +} +``` + +You cannot call `super()` in a class method, even if that method is called from the constructor: + +```js example-ba +class Base {} + +class Derived extends Base { + constructor() { + this.init(); + } + + init() { + super(); + } +} +``` + +You cannot call `super()` in a function, even if the function is used as a constructor: + +```js example-bad +function Base(x) { + this.x = x; +} + +function Derived() { + super(1); +} + +Object.setPrototypeOf(Derived.prototype, Base.prototype); +Object.setPrototypeOf(Derived, Base); +``` + +### Valid cases + +You can call `super()` before calling any other method in the constructor: + +```js example-good +class Base {} + +class Derived extends Base { + constructor() { + super(); + this.init(); + } + + init() { + // ... + } +} +``` + +You can call `super()` in an arrow function that's nested within the constructor: + +```js example-good +class Base {} + +class Derived extends Base { + constructor() { + const init = () => { + super(); + }; + + init(); + } +} +``` + +## See also + +- [Classes](/en-US/docs/Web/JavaScript/Reference/Classes) +- {{jsxref("Operators/super", "super")}} diff --git a/files/en-us/web/javascript/reference/errors/bad_super_prop/index.md b/files/en-us/web/javascript/reference/errors/bad_super_prop/index.md new file mode 100644 index 000000000000000..5aafd92583820a0 --- /dev/null +++ b/files/en-us/web/javascript/reference/errors/bad_super_prop/index.md @@ -0,0 +1,97 @@ +--- +title: "SyntaxError: use of super property/member accesses only valid within methods or eval code within methods" +slug: Web/JavaScript/Reference/Errors/Bad_super_prop +page-type: javascript-error +--- + +{{jsSidebar("Errors")}} + +The JavaScript exception "use of super property/member accesses only valid within methods or eval code within methods" occurs when the {{jsxref("Operators/super", "super.x")}} or `super[x]` syntax is used outside of a [method](/en-US/docs/Web/JavaScript/Reference/Functions/Method_definitions). + +## Message + +```plain +SyntaxError: 'super' keyword unexpected here (V8-based) +SyntaxError: use of super property accesses only valid within methods or eval code within methods (Firefox) +SyntaxError: super is not valid in this context. (Safari) +``` + +## Error type + +{{jsxref("SyntaxError")}} + +## What went wrong? + +The `super.x` syntax is used to access properties on the prototype of the current object. It can be used in methods of both [object literals](/en-US/docs/Web/JavaScript/Reference/Operators/Object_initializer) and [classes](/en-US/docs/Web/JavaScript/Reference/Classes), [field initializers](/en-US/docs/Web/JavaScript/Reference/Classes/Public_class_fields), and [static initialization blocks](/en-US/docs/Web/JavaScript/Reference/Classes/Static_initialization_blocks), but not in other contexts. + +## Examples + +### Invalid cases + +You can't use `super.x` outside of a method in an object: + +```js example-bad +const obj = { + __proto__: { x: 1 }, + x: super.x, // SyntaxError +}; +``` + +You can't use `super.x` in a function, even if that function has the effect of being a method: + +```js example-bad +function getX() { + return super.x; // SyntaxError +} + +const obj = { + getX, + getX2: function () { + return super.x; // SyntaxError + }, +}; + +class Derived extends Base { + getX = () => super.x; +} +``` + +### Valid cases + +You can use `super.x` in a method: + +```js example-good +class Base { + x = 1; +} + +class Derived extends Base { + getX() { + return super.x; + } +} +``` + +You can use `super.x` in a field initializer: + +```js example-good +class Derived extends Base { + x = super.x; +} +``` + +You can use `super.x` in object methods too: + +```js example-good +const obj = { + __proto__: { x: 1 }, + getX() { + return super.x; + }, +}; +``` + +## See also + +- [Classes](/en-US/docs/Web/JavaScript/Reference/Classes) +- {{jsxref("Operators/super", "super")}} diff --git a/files/en-us/web/javascript/reference/errors/builtin_ctor_no_new/index.md b/files/en-us/web/javascript/reference/errors/builtin_ctor_no_new/index.md new file mode 100644 index 000000000000000..342021f2b82e437 --- /dev/null +++ b/files/en-us/web/javascript/reference/errors/builtin_ctor_no_new/index.md @@ -0,0 +1,56 @@ +--- +title: "TypeError: calling a builtin X constructor without new is forbidden" +slug: Web/JavaScript/Reference/Errors/Builtin_ctor_no_new +page-type: javascript-error +--- + +{{jsSidebar("Errors")}} + +The JavaScript exception "calling a builtin X constructor without new is forbidden" occurs when you try to call a builtin constructor without using the {{jsxref("Operators/new", "new")}} keyword. All modern constructors, such as {{jsxref("Promise")}} and {{jsxref("Map")}}, must be called with `new`. + +## Message + +```plain +TypeError: Constructor X requires 'new' (V8-based) +TypeError: Promise constructor cannot be invoked without 'new' (V8-based) +TypeError: calling a builtin X constructor without new is forbidden (Firefox) +TypeError: calling X constructor without new is invalid (Safari) +``` + +## Error type + +{{jsxref("TypeError")}} + +## What went wrong? + +In JavaScript, _calling_ a function without `new` and _constructing_ a function with `new` are two distinct operations, and functions can behave differently depending on how they are called. + +Apart from the following legacy constructors, all modern constructors must be called with `new`: + +- {{jsxref("Object/Object", "Object()")}} +- {{jsxref("Function/Function", "Function()")}} (and its subclasses) +- {{jsxref("Error/Error", "Error()")}} (and its subclasses) +- {{jsxref("RegExp/RegExp", "RegExp()")}} +- {{jsxref("Array/Array", "Array()")}} + +Some other constructors, such as {{jsxref("Date/Date", "Date()")}}, and primitive wrappers, such as {{jsxref("String/String", "String()")}}, {{jsxref("Number/Number", "Number()")}}, and {{jsxref("Boolean/Boolean", "Boolean()")}}, can also be called with or without `new`, but the return types differ in the two cases. + +On every constructor page, you can find information about whether the constructor must be called with `new`. + +## Examples + +### Invalid cases + +```js example-bad +const m = Map(); // TypeError: calling a builtin Map constructor without new is forbidden +``` + +### Valid cases + +```js example-good +const m = new Map(); +``` + +## See also + +- {{jsxref("Operators/new", "new")}} diff --git a/files/en-us/web/javascript/reference/errors/class_ctor_no_new/index.md b/files/en-us/web/javascript/reference/errors/class_ctor_no_new/index.md new file mode 100644 index 000000000000000..ba12393c2279185 --- /dev/null +++ b/files/en-us/web/javascript/reference/errors/class_ctor_no_new/index.md @@ -0,0 +1,51 @@ +--- +title: "TypeError: class constructors must be invoked with 'new'" +slug: Web/JavaScript/Reference/Errors/Class_ctor_no_new +page-type: javascript-error +--- + +{{jsSidebar("Errors")}} + +The JavaScript exception "class constructors must be invoked with 'new'" occurs when a [class constructor](/en-US/docs/Web/JavaScript/Reference/Classes) is called without the {{jsxref("Operators/new", "new")}} keyword. All class constructors must be called with `new`. + +## Message + +```plain +TypeError: Class constructor X cannot be invoked without 'new' (V8-based) +TypeError: Class constructors cannot be invoked without 'new' (V8-based) +TypeError: class constructors must be invoked with 'new' (Firefox) +TypeError: Cannot call a class constructor without |new| (Safari) +``` + +## Error type + +{{jsxref("TypeError")}} + +## What went wrong? + +In JavaScript, _calling_ a function without `new` and _constructing_ a function with `new` are two distinct operations, and functions can behave differently depending on how they are called. + +Traditionally, JavaScript functions have been used as both constructors and normal functions, and can detect how they were called using [`new.target`](/en-US/docs/Web/JavaScript/Reference/Operators/new.target). However, class constructors are always constructors and cannot be called as normal functions. + +## Examples + +### Invalid cases + +```js example-bad +class X {} + +X(); // TypeError: class constructors must be invoked with 'new' +``` + +### Valid cases + +```js example-good +class X {} + +new X(); +``` + +## See also + +- [Classes](/en-US/docs/Web/JavaScript/Reference/Classes) +- {{jsxref("Operators/new", "new")}} diff --git a/files/en-us/web/javascript/reference/errors/constructor_cant_be_used_directly/index.md b/files/en-us/web/javascript/reference/errors/constructor_cant_be_used_directly/index.md new file mode 100644 index 000000000000000..51241398b9a6460 --- /dev/null +++ b/files/en-us/web/javascript/reference/errors/constructor_cant_be_used_directly/index.md @@ -0,0 +1,66 @@ +--- +title: "TypeError: Iterator/AsyncIterator constructor can't be used directly" +slug: Web/JavaScript/Reference/Errors/Constructor_cant_be_used_directly +page-type: javascript-error +--- + +{{jsSidebar("Errors")}} + +The JavaScript exception "Iterator constructor can't be used directly" or "AsyncIterator constructor can't be used directly" occurs when you try to use the {{jsxref("Iterator/Iterator", "Iterator()")}} or {{jsxref("AsyncIterator/AsyncIterator", "AsyncIterator()")}} constructors directly to create instances. These constructors are _abstract classes_ and should only be inherited from. + +## Message + +```plain +TypeError: Abstract class Iterator not directly constructable (V8-based) +TypeError: Iterator constructor can't be used directly (Firefox) +TypeError: Iterator cannot be constructed directly (Safari) + +TypeError: Abstract class AsyncIterator not directly constructable (V8-based) +TypeError: AsyncIterator constructor can't be used directly (Firefox) +TypeError: AsyncIterator cannot be constructed directly (Safari) +``` + +## Error type + +{{jsxref("TypeError")}} + +## What went wrong? + +The {{jsxref("Iterator")}} and {{jsxref("AsyncIterator")}} constructors are abstract classes and should not be used directly. They check the value of [`new.target`](/en-US/docs/Web/JavaScript/Reference/Operators/new.target) and throw if it is the same as the constructor itself. The only way to use these constructors is to inherit from them in a subclass and call `super()` in the subclass constructor. The subclass must also define a `next()` method to be useful. + +## Examples + +### Invalid cases + +```js example-bad +new Iterator(); +``` + +### Valid cases + +```js example-good +class MyIterator extends Iterator { + #step; + #end; + constructor(start, end) { + // Implicitly calls new Iterator(), but with a different `new.target` + super(); + this.#step = start; + this.#end = end; + } + next() { + if (this.#step < this.#end) { + return { value: this.#step++, done: false }; + } else { + return { done: true }; + } + } +} + +new MyIterator(); +``` + +## See also + +- {{jsxref("AsyncIterator")}} +- {{jsxref("Iterator")}} diff --git a/files/en-us/web/javascript/reference/errors/invalid_derived_return/index.md b/files/en-us/web/javascript/reference/errors/invalid_derived_return/index.md new file mode 100644 index 000000000000000..8f395d1f1135f9e --- /dev/null +++ b/files/en-us/web/javascript/reference/errors/invalid_derived_return/index.md @@ -0,0 +1,65 @@ +--- +title: "TypeError: derived class constructor returned invalid value x" +slug: Web/JavaScript/Reference/Errors/Invalid_derived_return +page-type: javascript-error +--- + +{{jsSidebar("Errors")}} + +The JavaScript exception "derived class constructor returned invalid value x" occurs when a derived class constructor returns a value that is not an object or `undefined`. + +## Message + +```plain +TypeError: Derived constructors may only return object or undefined (V8-based) +TypeError: derived class constructor returned invalid value 1 (Firefox) +TypeError: Cannot return a non-object type in the constructor of a derived class. (Safari) +``` + +## Error type + +{{jsxref("TypeError")}} + +## What went wrong? + +Typically, a constructor does not need to return anything—the value of `this` is automatically returned when the class is constructed. A constructor can also return an object, and this object will override `this` as the newly constructed instance. However, returning something that's neither an object nor `undefined` is usually a mistake, because that value is ignored. In base classes and function constructors (using the `function` syntax), returning such a value is silently ignored, while in derived classes, it throws an error. + +## Examples + +### Invalid cases + +```js example-bad +class Base { + constructor() {} +} + +class Derived extends Base { + constructor() { + return 2; + } +} + +new Derived(); // TypeError: derived class constructor returned invalid value 2 +``` + +### Valid cases + +```js example-good +class Base { + constructor() {} +} + +class Derived extends Base { + constructor() { + return { x: 1 }; + } +} + +new Derived(); // { x: 1 } +``` + +## See also + +- [Classes](/en-US/docs/Web/JavaScript/Reference/Classes) +- {{jsxref("Classes/extends", "extends")}} +- {{jsxref("Operators/new", "new")}} diff --git a/files/en-us/web/javascript/reference/errors/super_called_twice/index.md b/files/en-us/web/javascript/reference/errors/super_called_twice/index.md new file mode 100644 index 000000000000000..368bf8f4102b6a3 --- /dev/null +++ b/files/en-us/web/javascript/reference/errors/super_called_twice/index.md @@ -0,0 +1,85 @@ +--- +title: "ReferenceError: super() called twice in derived class constructor" +slug: Web/JavaScript/Reference/Errors/Super_called_twice +page-type: javascript-error +--- + +{{jsSidebar("Errors")}} + +The JavaScript exception "super() called twice in derived class constructor" occurs when the {{jsxref("Operators/super", "super()")}} is called a second time for a given derived class constructor. + +## Message + +```plain +ReferenceError: Super constructor may only be called once (V8-based) +ReferenceError: super() called twice in derived class constructor (Firefox) +ReferenceError: 'super()' can't be called more than once in a constructor. (Safari) +``` + +## Error type + +{{jsxref("ReferenceError")}} + +## What went wrong? + +The `super()` call can only be called at most once for each `new` call to a derived class constructor. This is because `super()` is responsible for initializing the parent class, and calling it more than once would result in the parent constructor being called multiple times. + +The best way to prevent this is to ensure that `super()` is placed outside of any control flow structure. Otherwise, make sure that all code paths in the constructor lead to only one `super()` call. + +The `super()` call can be "saved" in an arrow function nested within the constructor. Then, when you call the arrow function, you will also call `super()`, and the same rule applies: the arrow function can only be called at most once. + +## Examples + +### Invalid cases + +```js example-bad +class Base {} + +class Derived extends Base { + constructor() { + super(); + super(); + } +} +``` + +Sometimes the bug may be more subtle. + +```js example-bad +class Base { + constructor(flavor) { + // Do something with the flavor + } +} + +class Derived extends Base { + constructor(flavors) { + if (flavors.includes("chocolate")) { + super("chocolate"); + } + if (flavors.includes("vanilla")) { + super("vanilla"); + } + } +} +``` + +Originally, `flavors` may never simultaneously include both "chocolate" and "vanilla", but if that ever happens, the constructor will call `super()` twice. You need to rethink about how your class should be structured to avoid this issue. + +### Valid cases + +```js example-good +class Base {} + +class Derived extends Base { + constructor() { + super(); + // More initialization logic + } +} +``` + +## See also + +- [Classes](/en-US/docs/Web/JavaScript/Reference/Classes) +- {{jsxref("Operators/super", "super")}} diff --git a/files/en-us/web/javascript/reference/errors/super_not_called/index.md b/files/en-us/web/javascript/reference/errors/super_not_called/index.md new file mode 100644 index 000000000000000..f01cd13f9f9065b --- /dev/null +++ b/files/en-us/web/javascript/reference/errors/super_not_called/index.md @@ -0,0 +1,67 @@ +--- +title: "ReferenceError: must call super constructor before using 'this' in derived class constructor" +slug: Web/JavaScript/Reference/Errors/Super_not_called +page-type: javascript-error +--- + +{{jsSidebar("Errors")}} + +The JavaScript exception "must call super constructor before using 'this' in derived class constructor" occurs when the {{jsxref("Operators/super", "super()")}} is not called for a given derived class constructor, and the derived constructor tries to access the value of {{jsxref("Operators/this", "this")}}, or the derived constructor has already returned and the return value is not an object. + +## Message + +```plain +ReferenceError: Must call super constructor in derived class before accessing 'this' or returning from derived constructor (V8-based) +ReferenceError: must call super constructor before using 'this' in derived class constructor (Firefox) +ReferenceError: 'super()' must be called in derived constructor before accessing |this| or returning non-object. (Safari) +``` + +## Error type + +{{jsxref("ReferenceError")}} + +## What went wrong? + +The `super()` call can only be called at most once for each `new` call to a derived class constructor. Often, you need to call it exactly once, because if you don't call it, the parent constructor cannot initialize the value of `this`, so you cannot access `this` in the derived constructor and the `this` is not considered a valid constructed object (and throws if the derived constructor completes in this state). The way around it is to return an object from the derived class constructor, in which case the object returned will be used as the constructed object instead of `this`, allowing you to not call `super()`. This is rarely done though. + +## Examples + +### Invalid cases + +```js example-bad +class Base { + constructor() { + this.x = 1; + } +} + +class Derived extends Base { + constructor() { + console.log(this.x); + // The Base constructor is not called yet, so this.x is undefined + // ReferenceError: must call super constructor before using 'this' in derived class constructor + } +} +``` + +### Valid cases + +```js example-good +class Base { + constructor() { + this.x = 1; + } +} + +class Derived extends Base { + constructor() { + super(); + console.log(this.x); // 1 + } +} +``` + +## See also + +- [Classes](/en-US/docs/Web/JavaScript/Reference/Classes) +- {{jsxref("Operators/super", "super")}}