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

In-Game: Throw an exception when calling a constructor function without the "new" keyword #7690

Closed
kat-fl opened this issue Sep 18, 2024 · 7 comments
Assignees
Labels
documentation Improvements or additions to documentation are required by this issue feature request New feature (or a request for one)
Milestone

Comments

@kat-fl
Copy link
Member

kat-fl commented Sep 18, 2024

Is your feature request related to a problem?

In YYC and GMRT, the following code will construct an instance of Bee instead of Cas:

function Cas() constructor {
  show_debug_message("Calling Cas");
  Bee();
}

function Bee() constructor {
  show_debug_message("Calling Bee");
}

var bee = new Cas();
show_message(instanceof(bee)); // Bee

Describe the solution you'd like

A runtime error when calling a constructor function without new. Bee() should be a runtime error like "cannot call a constructor without the 'new' keyword".

Describe alternatives you've considered

No response

Additional context

No response

@rwkay
Copy link

rwkay commented Sep 19, 2024

Feature added in 2024.11 - an error will be thrown if a constructor is called normally - they MUST be called with new

@rwkay rwkay closed this as completed Sep 19, 2024
@github-project-automation github-project-automation bot moved this from Todo to Done in Team Workload Sep 19, 2024
@YYDan YYDan changed the title Throw an exception when calling a constructor function without new In-Game: Throw an exception when calling a constructor function without the "new" keyword Sep 19, 2024
@gurpreetsinghmatharoo gurpreetsinghmatharoo added the documentation Improvements or additions to documentation are required by this issue label Sep 19, 2024
@gurpreetsinghmatharoo gurpreetsinghmatharoo moved this from Done to Ready for QA in Team Workload Sep 19, 2024
gurpreetsinghmatharoo added a commit to YoYoGames/GameMaker-Manual that referenced this issue Sep 19, 2024
@Hyomoto
Copy link

Hyomoto commented Sep 20, 2024

For clarity, can we have some answer as to why constructor exists then? New and constructor seem to both perform the same task: indicate to the engine that this code produces structs. The JS we're seemingly emulating uses new but doesn't use constructor. Thus, while new never worked on non-constructor calls, constructors could be called without new. Weird, but a quirk of two keywords.

As with my post on #3055, with this change, we can now say, without exception, one of them is superfluous. If we've decided new, arguably the less important of the two, is now vital then we shouldn't need to declare constructors anymore. If we admit that constructor is important, then new is completely unneccessary as the identity of the constructor is to BE a constructor. Enforcing the use of new only ensures this is true and adds a language keyword that actually does nothing but throw runtime errors when omitted.

Thus one can easily argue that removing new also solves this problem as calling a constructor, which has been declared as a constructor, should be sufficient to indicate to the engine it's purpose and also close the aforementioned since constructors would be legal to call with method_call and return the expected results. In short, the fix here is patching a hole that only exists because the implementation uses two keywords and changing that both breaks prior functionality and makes one keyword pointless.

@yerumaku
Copy link

@Hyomoto

As with my post on #3055, with this change, we can now say, without exception, one of them is superfluous. If we've decided new, arguably the less important of the two, is now vital then we shouldn't need to declare constructors anymore.

You are absolutely wrong. The constructor keyword is needed in order to show that this function is a constructor and the result of its correct call with the new keyword is a structure, and with a certain static binding, that is, it replaces return struct (as CtorName). Running the constructor without the keyword new allows you to initialize static fields, or inject structure fields from ctor-function into an instance of an object or other structure where it is called, this is also part of the inherent logic that you did not see.

@Hyomoto
Copy link

Hyomoto commented Sep 20, 2024

@Hyomoto

As with my post on #3055, with this change, we can now say, without exception, one of them is superfluous. If we've decided new, arguably the less important of the two, is now vital then we shouldn't need to declare constructors anymore.

You are absolutely wrong. The constructor keyword is needed in order to show that this function is a constructor and the result of its correct call with the new keyword is a structure, and with a certain static binding, that is, it replaces return struct (as CtorName). Running the constructor without the keyword new allows you to initialize static fields, or inject structure fields from ctor-function into an instance of an object or other structure where it is called, this is also part of the inherent logic that you did not see.

Perhaps, except the fix here requires the use of new with a function explicitly flagged as a constructor. We have drawn an explicit link from a new declaration to a constructor declaration, if the two must be used together and can not be used without one another, we have one keyword too many. In this condition the nature of the call can be inferred from constructor or new, there is no other legal pairing.

After all, the runtime error being added proves the interpreter can recognize this.

@sihammill
Copy link

Fix verified in Beta IDE v2024.1100.0.626 Beta Runtime v2024.1100.0.652

@sihammill sihammill moved this from Ready for QA to Verified in Team Workload Sep 26, 2024
@StarJackal57
Copy link

This now also throws an error for constructor inheritance because that requires you to call the parent constructor without using "new".
image

@RefresherTowel
Copy link

RefresherTowel commented Sep 28, 2024

This is still a problem in Beta v2024.1100.0.652. Constructor inheritance is broken as the parent cannot be invoked without a new command.
Screenshot (653)
Very simple project just consisting of a parent and child constructor, with the child constructor being called properly with the new command. As you can see in the output, the project fails to compile because the child is not invoking the parent properly. This happens with both GMS2 VM and GMS2 YYC.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation Improvements or additions to documentation are required by this issue feature request New feature (or a request for one)
Projects
Status: Verified
Development

No branches or pull requests

9 participants