Skip to content
Snippets Groups Projects
Select Git revision
  • 7dec8b3721b40ecdcf921418e20f8e8ca7b2e1cf
  • wk2/unstable default
  • fix-raspi-issues-v2-oracular
  • fix-raspi-issues-v2-noble
  • fix-raspi-issues-v2
  • fix-raspi-issues
  • wpe/unstable
  • wpewebkit-2.44
  • berto/wk2/bookworm
  • berto/wk2/bullseye
  • webkitgtk-2.44
  • wk2/experimental
  • wpewebkit-2.42
  • webkitgtk-2.42
  • webkitgtk-2.40
  • wpewebkit-2.40
  • buster
  • webkitgtk-2.38
  • wpewebkit-2.38
  • wpewebkit-2.36
  • webkitgtk-2.36
  • wpe/debian/2.44.1-1
  • wpe/upstream/2.44.1
  • debian/2.44.1-1
  • upstream/2.44.1
  • debian/2.44.0-2
  • debian/2.44.0-1
  • upstream/2.44.0
  • debian/2.43.4-2
  • debian/2.42.5-2
  • wpe/debian/2.42.5-1.2
  • wpe/debian/2.42.5-2_exp
  • wpe/debian/2.42.5-1.1
  • debian/2.42.5-1_deb11u1
  • debian/2.42.5-1_deb12u1
  • wpe/debian/2.42.5-1
  • wpe/upstream/2.42.5
  • debian/2.42.5-1
  • upstream/2.42.5
  • debian/2.43.4-1
  • upstream/2.43.4
41 results

generate-js-builtins

Blame
  • Forked from WebKit / webkit
    Source project has a limited visibility.
    generate-js-builtins 11.82 KiB
    #!/usr/bin/python
    # Copyright (C) 2014 Apple Inc. All rights reserved.
    #
    # Redistribution and use in source and binary forms, with or without
    # modification, are permitted provided that the following conditions
    # are met:
    # 1. Redistributions of source code must retain the above copyright
    #    notice, this list of conditions and the following disclaimer.
    # 2. Redistributions in binary form must reproduce the above copyright
    #    notice, this list of conditions and the following disclaimer in the
    #    documentation and/or other materials provided with the distribution.
    #
    # THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
    # EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
    # PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
    # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
    # EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
    # PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
    # PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
    # OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    
    import argparse
    import filecmp
    import fnmatch
    import os
    import re
    import shutil
    import sys
    import datetime
    import json
    
    parser = argparse.ArgumentParser()
    parser.add_argument('input_file', nargs='*', help='Input JS files which builtins generated from')
    parser.add_argument('--input-directory', help='All JS files will be used as input from this directory.')
    parser.add_argument('--output', help='path to output cpp or h file')
    args = parser.parse_args()
    
    copyrightText = """ *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     * 1. Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     * 2. Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
     * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
     * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
     * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
     */\n
    """
    
    generatorString = "/* Generated by %s do not hand edit. */\n" % os.path.basename(__file__)
    
    functionHeadRegExp = re.compile(r"(?:function|constructor)\s+\w+\s*\(.*?\)", re.MULTILINE | re.S)
    functionNameRegExp = re.compile(r"(?:function|constructor)\s+(\w+)\s*\(", re.MULTILINE | re.S)
    functionIsConstructorRegExp = re.compile(r"^constructor", re.MULTILINE | re.S)
    functionParameterFinder = re.compile(r"^(?:function|constructor)\s+(?:\w+)\s*\(((?:\s*\w+)?\s*(?:\s*,\s*\w+)*)?\s*\)", re.MULTILINE | re.S)
    
    multilineCommentRegExp = re.compile(r"\/\*.*?\*\/", re.MULTILINE | re.S)
    singleLineCommentRegExp = re.compile(r"\/\/.*?\n", re.MULTILINE | re.S)
    
    def getCopyright(source):
        copyrightBlock = multilineCommentRegExp.findall(source)[0]
        copyrightBlock = copyrightBlock[:copyrightBlock.index("Redistribution")]
        copyRightLines = []
    
        for line in copyrightBlock.split("\n"):
            line = line.replace("/*", "")
            line = line.replace("*/", "")
            line = line.replace("*", "")
            line = line.replace("Copyright", "")
            line = line.replace("copyright", "")
            line = line.replace("(C)", "")
            line = line.replace("(c)", "")
            line = line.strip()
            if len(line) == 0:
                continue
    
            copyRightLines.append(line)
        
        return list(set(copyRightLines))
    
    class Function(object):
        def __init__(self, name, source, isConstructor, parameters):
            self.name = name
            self.source = source
            self.isConstructor = isConstructor
            self.parameters = parameters
    
        def mangleName(self, object):
            qName = object + "." + self.name
            mangledName = ""
            i = 0
            while i < len(qName):
                if qName[i] == '.':
                    mangledName = mangledName + qName[i + 1].upper()
                    i = i + 1
                else:
                    mangledName = mangledName + qName[i]
                i = i + 1
            if self.isConstructor:
                mangledName = mangledName + "Constructor"
            return mangledName
    
    def getFunctions(source):
    
        source = multilineCommentRegExp.sub("/**/", singleLineCommentRegExp.sub("//\n", source))
    
        matches = [ f for f in functionHeadRegExp.finditer(source)]
        functionBounds = []
        start = 0
        end = 0
        for match in matches:
            start = match.start()
            if start < end:
                continue
            end = match.end()
            while source[end] != '{':
                end = end + 1
            depth = 1
            end = end + 1
            while depth > 0:
                if source[end] == '{':
                    depth = depth + 1
                elif source[end] == '}':
                    depth = depth - 1
                end = end + 1
            functionBounds.append((start, end))
    
        functions = [source[start:end].strip() for (start, end) in functionBounds]
        result = []
        for function in functions:
            function = multilineCommentRegExp.sub("", function)
            functionName = functionNameRegExp.findall(function)[0]
            functionIsConstructor = functionIsConstructorRegExp.match(function) != None
            functionParameters = functionParameterFinder.findall(function)[0].split(',')
            if len(functionParameters[0]) == 0:
                functionParameters = []
    
            result.append(Function(functionName, function, functionIsConstructor, functionParameters))
        return result
    
    
    def generateCode(source):
        inputFile = open(source, "r")
        baseName = os.path.basename(source).replace(".js", "")
        
        source = ""
        for line in inputFile:
            source = source + line
        
        if sys.platform == "cygwin":
            source = source.replace("\r\n", "\n")
        return (baseName, getFunctions(source), getCopyright(source))
    
    builtins = []
    copyrights = []
    (output_base, _) = os.path.splitext(args.output)
    
    if args.input_directory:
        for file in os.listdir(args.input_directory):
            args.input_file.append(os.path.join(args.input_directory, file))
    
    for file in args.input_file:
        if fnmatch.fnmatch(file, '*.js'):
            (baseName, functions, objectCopyrights) = generateCode(file)
            copyrights.extend(objectCopyrights)
            builtins.append((baseName, functions))
    
    copyrights = list(set(copyrights))
    
    copyrightBody = ""
    for copyright in copyrights:
        copyrightBody = copyrightBody +" * Copyright (C) " + copyright + "\n"
    
    builtinsHeader = open(output_base + ".h.tmp", "w")
    builtinsImplementation = open(output_base + ".cpp.tmp", "w")
    copyrightText = "/*\n" + copyrightBody + copyrightText
    builtinsHeader.write("""%s
    %s
    
    #ifndef JSCBuiltins_H
    #define JSCBuiltins_H
    
    #include "ConstructAbility.h"
    
    namespace JSC {
    
    class FunctionExecutable;
    class Identifier;
    class JSGlobalObject;
    class SourceCode;
    class UnlinkedFunctionExecutable;
    class VM;
    
    FunctionExecutable* createBuiltinExecutable(VM&, UnlinkedFunctionExecutable*, const SourceCode&);
    
    """ % (generatorString, copyrightText))
    
    codeReferences = []
    
    for (objectName, functions) in builtins:
        print("Generating bindings for the %s builtin." % objectName)
        builtinsHeader.write("/* %s functions */\n" % objectName)
        for function in functions:
            name = function.name
            mangledName = function.mangleName(objectName)
            mangledName = mangledName[0].lower() + mangledName[1:] + "Code"
            codeReferences.append((mangledName, function))
            builtinsHeader.write("extern const char* s_%s;\n" % mangledName)
            builtinsHeader.write("extern const int s_%sLength;\n" % mangledName)
            builtinsHeader.write("extern const ConstructAbility s_%sConstructAbility;\n" % mangledName)
        builtinsHeader.write("\n")
        builtinsHeader.write("#define JSC_FOREACH_%s_BUILTIN(macro) \\\n" % objectName.replace(".", "_").upper())
        for function in functions:
            mangledName = function.mangleName(objectName)
            builtinsHeader.write("    macro(%s, %s, %d) \\\n" % (function.name, mangledName, len(function.parameters)))
        builtinsHeader.write("\n")
        for function in functions:
            builtinsHeader.write("#define JSC_BUILTIN_%s 1\n" % function.mangleName(objectName).upper())
        builtinsHeader.write("\n\n")
    names = []
    builtinsHeader.write("#define JSC_FOREACH_BUILTIN(macro)\\\n")
    for (codeReference, function) in codeReferences:
        builtinsHeader.write("    macro(%s, %s, s_%sLength) \\\n" % (codeReference, function.name, codeReference))
        names.append(function.name)
    
    builtinsHeader.write("\n\n")
    builtinsHeader.write("#define JSC_FOREACH_BUILTIN_FUNCTION_NAME(macro) \\\n")
    for name in sorted(set(names)):
        builtinsHeader.write("    macro(%s) \\\n" % name)
    builtinsHeader.write("""
    
    #define JSC_DECLARE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
        FunctionExecutable* codeName##Generator(VM&);
    
    JSC_FOREACH_BUILTIN(JSC_DECLARE_BUILTIN_GENERATOR)
    #undef JSC_DECLARE_BUILTIN_GENERATOR
    
    #define JSC_BUILTIN_EXISTS(name) defined JSC_BUILTIN_ ## name
    
    }
    
    #endif
    
    """)
    
    builtinsImplementation.write("""%s
    %s
    
    #include "config.h"
    
    #include "JSCBuiltins.h"
    
    #include "BuiltinExecutables.h"
    #include "ConstructAbility.h"
    #include "Executable.h"
    #include "JSCellInlines.h"
    #include "VM.h"
    
    namespace JSC {
    
    """  % (generatorString, copyrightText))
    
    for (codeReference, function) in codeReferences:
        source = function.source
        source = "(function " + source[source.index("("):] + ")"
        lines = json.dumps(source)[1:-1].split("\\n")
        sourceLength = len(source)
        source = ""
        for line in lines:
            source = source + ("    \"%s\\n\" \\\n" % line)
        builtinsImplementation.write("const char* s_%s =\n%s;\n\n" % (codeReference, source))
        builtinsImplementation.write("const int s_%sLength = %d;\n\n" % (codeReference, sourceLength + 1)) # + 1 for \n
        constructAbility = "ConstructAbility::CannotConstruct"
        if function.isConstructor:
            constructAbility = "ConstructAbility::CanConstruct"
        builtinsImplementation.write("const ConstructAbility s_%sConstructAbility = %s;\n\n" % (codeReference, constructAbility)) # + 1 for \n
    
    builtinsImplementation.write("""
    #define JSC_DEFINE_BUILTIN_GENERATOR(codeName, functionName, argumentCount) \\
    FunctionExecutable* codeName##Generator(VM& vm) \\
    { \\
        return vm.builtinExecutables()->codeName##Executable()->link(vm, vm.builtinExecutables()->codeName##Source()); \\
    }
    
    JSC_FOREACH_BUILTIN(JSC_DEFINE_BUILTIN_GENERATOR)
    #undef JSC_DEFINE_BUILTIN_GENERATOR
    }
    
    """)
    
    builtinsHeader.close()
    builtinsImplementation.close()
    
    if (not os.path.exists(output_base + ".h")) or (not filecmp.cmp(output_base + ".h.tmp", output_base + ".h", shallow=False)):
        if (os.path.exists(output_base + ".h")):
            os.remove(output_base + ".h")
        os.rename(output_base + ".h.tmp", output_base + ".h")
    else:
        os.remove(output_base + ".h.tmp")
    
    if (not os.path.exists(output_base + ".cpp")) or (not filecmp.cmp(output_base + ".cpp.tmp", output_base + ".cpp", shallow=False)):
        if (os.path.exists(output_base + ".cpp")):
            os.remove(output_base + ".cpp")
        os.rename(output_base + ".cpp.tmp", output_base + ".cpp")
    else:
        os.remove(output_base + ".cpp.tmp")