public function getScript()
    {
        $this->createCallableObjects();

        $sPrefix = $this->getOption('core.prefix.class');

        $aJsClasses = [];
        $sCode = '';
        foreach(array_keys($this->aNamespaces) as $sNamespace)
        {
            $offset = 0;
            $sJsNamespace = str_replace('\\', '.', $sNamespace);
            $sJsNamespace .= '.Null'; // This is a sentinel. The last token is not processed in the while loop.
            while(($dotPosition = strpos($sJsNamespace, '.', $offset)) !== false)
            {
                $sJsClass = substr($sJsNamespace, 0, $dotPosition);
                // Generate code for this object
                if(!key_exists($sJsClass, $aJsClasses))
                {
                    $sCode .= "$sPrefix$sJsClass = {};\n";
                    $aJsClasses[$sJsClass] = $sJsClass;
                }
                $offset = $dotPosition + 1;
            }
        }

        foreach($this->aCallableObjects as $sClassName => $xCallableObject)
        {
            $aConfig = $this->aCallableOptions[$sClassName];
            $aCommonConfig = key_exists('*', $aConfig) ? $aConfig['*'] : [];

            $aMethods = [];
            foreach($xCallableObject->getMethods() as $sMethodName)
            {
                // Specific options for this method
                $aMethodConfig = key_exists($sMethodName, $aConfig) ?
                    array_merge($aCommonConfig, $aConfig[$sMethodName]) : $aCommonConfig;
                $aMethods[] = [
                    'name' => $sMethodName,
                    'config' => $aMethodConfig,
                ];
            }

            $sCode .= $this->render('jaxon::support/object.js', [
                'sPrefix' => $sPrefix,
                'sClass' => $xCallableObject->getJsName(),
                'aMethods' => $aMethods,
            ]);
        }

        return $sCode;
    }