Page MenuHomePhabricator

Improve UTF-8 behaviour and error messages at mw.title
Open, Needs TriagePublic

Description

I happened to retrieve a page name from a wiki URL, grabbed the title, but got a crash with

mw.title.lua:354: attempt to index local 'b' (a nil value)

Current situation

Step to reproduce

Enter this in a Lua inspection field:

=mw.title.makeTitle( "Project", "M%C3%BCnchen" )

Expected result

"Project:München"

or a mw.title object in code.

Current result

nil

No title object.

Follow-up error

Passing the supposed mw.title object to mw.title.equals() this crashes with the less informative message

mw.title.lua:354: attempt to index local 'b' (a nil value)

It left me a bit confused.

What should happen?

  1. Different from PHP, Lua code could be gracious if page titles do contain UTF-8 encoding. Within wikitext, [[M%C3%BCnchen]] works fine.
  2. If mw.title.equals() or others are called with invalid parameters, an informative message should appear rather than system fallback. local function checkNamespace() is fine.

Possible solutions

For mw.title library, rELUA /includes/Engines/LuaCommon/lualib/mw.title.lua

Permit UTF-8 encoding

In checkNamespace()

local ns = mw.site.namespaces[ mw.uri.decode( arg ) ]

Alternatively, mw.site library might accept UTF-8 encoded namespaces.

function title.makeTitle( ns, title, fragment, interwiki )
    if type( title ) == 'string' then
        ns = checkNamespace( 'mw.title.makeTitle', 1, ns )
        title = mw.uri.decode( title )
        return makeTitleObject( php.makeTitle( ns, title, fragment, interwiki ) )
    else
        local msg = "bad argument 'title' to 'mw.title.makeTitle'"
        error( msg, 3 )
    end
end

equals() error message

function title.equals( a, b )
    if type( a ) == 'table' and type( b ) == 'table' then
        return a.interwiki == b.interwiki and
            a.namespace == b.namespace and
            a.text == b.text
    else
        local msg = "bad argument to 'mw.title.equals'"
        error( msg, 3 )
    end
end

compare() error message

function title.compare( a, b )
    if type( a ) == 'table' and type( b ) == 'table' then
        if a.interwiki ~= b.interwiki then
            return a.interwiki < b.interwiki and -1 or 1
        end
        if a.namespace ~= b.namespace then
            return a.namespace < b.namespace and -1 or 1
        end
        if a.text ~= b.text then
            return a.text < b.text and -1 or 1
        end
        return 0
    else
        local msg = "bad argument to 'mw.title.compare'"
        error( msg, 3 )
    end
end

More precise location

Add library prefix to message, since at least equals() and compare() might occur in any object.

ns = checkNamespace( 'mw.title.inNamespace', 1, ns )
ns = checkNamespace( 'mw.title.inNamespaces', i, select( i, ... ) )
ns = checkNamespace( 'mw.title.hasSubjectNamespace', 1, ns )

Or within checkNamespace() itself.