0

I'm trying to build a Chrome extension with TypeScript.
The setup is quite simple:

In manifest.json

{   
    "permissions": [
        "webRequest",
        "webRequestBlocking",
        "tabs",
        "storage",
        "http://*/",
        "https://*/*"
    ],

    "content_scripts": [
     {
        "matches": [ "http://*/*", "https://*/*" ],
        "js": [ "scripts/require.js", "scripts/require-cs.js",
                "scripts/main.js", "scripts/contentscript.js" ],
        "run_at": "document_end",
        "all_frames": true
     }],
}

In model.ts:

export class WebPage
{
    private id: number;
    private processed: boolean;

    get Id() { return this.id; }
    set Id(value: number) { this.id = value };

    get Processed() { return this.processed; }
    set Processed(value: boolean) { this.processed = value };

    constructor(id: number)
    {
        this.id = id;
        this.processed = false;
    }
}

When compiled the resulting JavaScript starts with:

define(["require", "exports"], function (require, exports) {
    var WebPage = (function () 
    {
           //Code omitted to keep the SO question short
    }});

In main.ts:

(function ()
{
    console.log("Executing main.js");

    requirejs.config(
        {
            baseUrl: "scripts", paths: { "model" : "model" }
        });
})();

In contentscript.ts:

import model = require("model");

console.log("Processing page");
var page = new model.WebPage(1);
page.Processed = true;
console.log("Done processing page");

When compiled the resulting JavaScript looks like this:

define(["require", "exports", "model"], function (require, exports, model) {
    console.log("Processing page");
    var page = new model.WebPage(1);
    page.Processed = true;
    console.log("Done processing page");
});

And finally in require-cs.js:

console.log("Executing requirejs-cs.js");

require.load = function (context, moduleName, url) {

    console.log("require.load called");
    var xhr = new XMLHttpRequest();

    xhr.open("GET", chrome.extension.getURL(url) + '?r=' + (new Date()).getTime(), true);

    xhr.onreadystatechange = function (e) {
        if (xhr.readyState === 4 && xhr.status === 200) {
            console.log("evaluating" + url)
            eval(xhr.responseText);
            context.completeLoad(moduleName);
        }
    };
    xhr.send(null);
};

Which is what I found in all the other questions related to my issue.

All of this results in the following output when loading a page:

Uncaught Error: Mismatched anonymous define() module: function (require, exports, model) {
    console.log("Processing page");
    var page = new model.WebPage(1);
    page.Processed = true;
    console.log("Done processing page");
}
http://requirejs.org/docs/errors.html#mismatch

I've read those docs, I went through a lot of similar questions on SO,
but I haven't found anything that works for me yet.
Most questions deal with JavaScript specifically,
perhaps there is something missing on the TypeScript side of things?

Note: The TypeScript compiler is configured to use AMD.

1 Answer 1

2

The docs for the error message state:

Be sure to load all scripts that call define() via the RequireJS API. Do not manually code script tags in HTML to load scripts that have define() calls in them.

As described in this question, it seems that if you use import in a type script, it will be turned into a module when compiled using AMD. So by including "scripts/contentscript.js" as a content script you are trying to load a module script without using the RequireJS API. You can try removing contentscript.js from the content_scripts entry in the manifest and adding the following to main.js:

requirejs(["contentscript"], function() {});
Sign up to request clarification or add additional context in comments.

1 Comment

This does solve my problem for content scripts that are defined in the manifest, thank you. I looked at the docs but it just didn't click. Doesn't seem to work for content scripts executed from a background page, but that's for another question perhaps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.