Example #1
0
    def setup_sleep(cls):
        """Setup JavaScript analog of ``sleep`` function. """
        def jsext_sleep(amount):
            """Sleep the specified amount of time. """
            time.sleep(amount)

        src = 'native function sleep(arg);'
        ext = PyV8.JSExtension('sleep/python', src, lambda _: jsext_sleep)

        return ext.name
Example #2
0
    def setup_print(cls):
        """Setup JavaScript analog of ``print`` statement. """
        def jsext_print(*args):
            """Print values to stdout. """
            sys.stdout.write(' '.join(map(str, args)) + '\n')

        src = 'native function print(arg);'
        ext = PyV8.JSExtension('print/python', src, lambda _: jsext_print)

        return ext.name
Example #3
0
    def get_extensions(self, pagedir, extra_files):
        '''
        pagedir: 'pages-touch/index'
        '''
        suffix = '/'.join(extra_files)
        name = JS_EXTENSION_NAME % {'pagedir': pagedir,
                                    'suffix': suffix}
        ext = self.pageextensions.get(name)

        if ext is None:
            page_js = self.load_pagejs_data(pagedir, extra_files)
            ext = PyV8.JSExtension(name, page_js)
            self.pageextensions[name] = ext
        return name, ext
def transform_jsx(source, path=None):
    """
    Transform the given JSX source into regular Javascript and return
    the generated source.

    Also compile it into a PyV8 object and create an extension to
    embed in future PyV8 contexts.
    """
    log.debug("Transforming JSX for %r", path)
    if "lib/jsx" in PyV8.JSExtension.extensions:
        log.debug("JSX extension already loaded")
    else:
        with open(JSX_TRANSFORMER_PATH) as jsxf:
            jsx_transformer_js = jsxf.read()
        # Inject the `global` var which it needs to function -- ensure
        # that it doesn't clobber any existing global var though!
        jsx_transformer_js = """
var global = ("undefined"!==typeof global) ? global : {};
%s
var JSXTransfomer = global.JSXTransformer;
""" % jsx_transformer_js

        log.debug("Read JSXTransformer")
        ext = PyV8.JSExtension("lib/jsx", jsx_transformer_js)
        log.debug("Created extension: %r ; now the set is %r", ext,
                  PyV8.JSExtension.extensions)

    log.debug("Evaluating JSX")
    script = """
var jsxSource = %r;
global.JSXTransformer.transform(jsxSource);
""" % source

    with PyV8.JSContext(extensions=["lib/jsx"]) as ctx:
        log.debug("running in context: %r", ctx)
        result = ctx.eval(script)
        log.debug("evaluated: %r", result)
        result_code = result.code

    log.debug("Transformed JSX")
    return result_code
def make_js_bundle(app_js_path):
    """
    Compile the given application Javascript into a PyV8 JSExtension.
    Caches extensions it's compiled under their path, so if the path
    is already compiled doesn't do the work again.

    Transforms any JSX, not only compiling it as an extension but also
    writing it to a corresponding .js file for client-side loading.

    Also bundles the React and Moment.js libraries, which are used by
    the client-side code.
    """
    if app_js_path in PyV8.JSExtension.extensions:
        log.debug("Application code already loaded")
        return

    log.debug("Loading React library")
    if "lib/react" in PyV8.JSExtension.extensions:
        log.debug("Extension already loaded")
    else:
        start = time.time()
        with open(REACT_LIB_PATH, 'r') as react_f:
            react_js = react_f.read()
        log.debug("TIME: Read in %.3f", (time.time() - start) * 1000)
        # Ensure the `global` var is defined, as it's needed, but
        # don't destroy any existing context
        react_js = """
var global = ("undefined"!==typeof global) ? global : {};
%s
var React = global.React;
""" % react_js
        # Register the extension for later use
        ext = PyV8.JSExtension("lib/react", react_js)
        log.debug("Created extension: %r", ext)

    if "lib/moment" in PyV8.JSExtension.extensions:
        log.debug("Moment extension already loaded")
    else:
        start = time.time()
        with open(absolute_path_in_app("static/js/moment.min.js"), 'r') as m_f:
            moment_js = m_f.read()
        log.debug("TIME: Moment read in %.3f", (time.time() - start) * 1000)
        # Ensure global and window are defined so we can access the
        # library later
        moment_js = """
var window = ("undefined"!==typeof global) ? global : {};
%s
var moment = global.moment;
""" % moment_js
        # Register the extension for later use
        ext = PyV8.JSExtension("lib/moment", moment_js)
        log.debug("Created Moment extension: %r", ext)

    log.debug("Loading JS application code")
    start = time.time()
    with open(absolute_path_in_app(app_js_path), 'r') as app_f:
        app_js = app_f.read()

    if app_js_path.endswith('.jsx'):
        log.debug("Transforming JSX")
        app_js = transform_jsx(app_js, app_js_path)
        log.debug("Writing transformed JS")
        transformed_path = app_js_path.replace('jsx', 'js')
        with open(absolute_path_in_app(transformed_path), 'w') as out:
            out.write(app_js)
        log.debug("...done")

    log.debug("TIME: Loaded in %.3f", (time.time() - start) * 1000)

    start = time.time()
    ext = PyV8.JSExtension(app_js_path, app_js)
    log.debug("TIME: Compiled in %.3f", (time.time() - start) * 1000)