LadybirdBrowser / ladybird

Truly independent web browser
https://ladybird.org
BSD 2-Clause "Simplified" License
25.03k stars 1.08k forks source link

LibJS: Strict mode error even though strict mode should not be active #1798

Open fdellwing opened 1 month ago

fdellwing commented 1 month ago

This is a clone of https://github.com/SerenityOS/serenity/issues/23240


Simplified reproduction:

function foo() {}     
foo.arguments

Original issue:

1280.563 WebContent(1164): Unhandled JavaScript exception: [TypeError] Restricted function properties like 'callee', 'caller' and 'arguments' may not be accessed in strict mode
1280.563 WebContent(1164):     at <unknown>
    at WodItem (https://darkveil.world-of-dungeons.net/wod/javascript/orders.js?1702062237:224:16)
    at https://darkveil.world-of-dungeons.net/wod/javascript/orders.js?1702062237:293:17

=> https://darkveil.world-of-dungeons.net/wod/javascript/orders.js

function WodItem(id, name, classes, ammoClassIds, equipped, equipped_sockets, unequipped_sockets) {

    if (WodItem.arguments.length == 1) { // <- Error happens here

        if (THE_ENV.items[id]) {
            return THE_ENV.items[id]

        } else {
            this.id = id
            this.name = WOD_STR.Wod.item.unknown
            this.equipped = false
            this.classes  = classes
            this.ammoClassIds = ammoClassIds
            this.equipped_sockets = false
        }
    } else {
        this.id           = id
        this.name         = (equipped?'' : '!! ') + name
        this.classes      = classes
        this.ammoClassIds = ammoClassIds
        this.equipped     = equipped
        this.equipped_sockets  = equipped_sockets
        this.unequipped_sockets  = unequipped_sockets
    }
}

Neither the file nor the function use strict mode. The code obviously works in Firefox.

fdellwing commented 1 month ago

I did some debugging and we are not in AbstractOperations::create_mapped_arguments_object or AbstractOperations::create_unmapped_arguments_object, these would be called with something like:

function foo() {
    arguments[0]
};
foo(1);

This problem instead lies in this code: https://github.com/LadybirdBrowser/ladybird/blob/2b65e86ec7fb04d5c0e31256e80bee31a66c6d96/Userland/Libraries/LibJS/Runtime/Intrinsics.cpp#L425-L443

This code is blocking all calls to foo.arguments and foo.caller. And while this seems to be correct (?) regarding the spec, it clearly differs in behaviour from other browsers.

F3n67u commented 1 week ago

Access the arguments using Function.prototype.arguments is non-standard, below is a quote from MDN page of Function.prototype.arguments:

This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.

The recommended way to access the arguments object is to refer to the variable arguments available within functions.

I am not sure if Ladybird browser stills needs to support this non-standard feature.