web: Make `SourceAPI` a singleton

As a first step towards a simpler Web API, convert `SourceAPI` from
a class to a constant object, under the assumption that `SourceAPI`
isn't a public Ruffle API and as such is safe to be changed.

As a result the different `ruffle-core` users don't need to construct
a new `SourceAPI` instance before calling `PublicAPI.negotiate()`.
This commit is contained in:
relrelb 2022-06-03 21:50:51 +03:00 committed by Mike Welsh
parent 8d30833d02
commit 1accf2d8f9
7 changed files with 26 additions and 61 deletions

View File

@ -9,7 +9,6 @@ export * from "./ruffle-imports";
export * from "./ruffle-object";
export * from "./ruffle-player";
export * from "./shadow-template";
export * from "./source-api";
export * from "./version";
export * from "./version-range";
export * from "./config";

View File

@ -32,7 +32,7 @@ export class PublicAPI {
*/
config: Config;
private sources: Record<string, SourceAPI>;
private sources: Record<string, typeof SourceAPI>;
private invoked: boolean;
private newestName: string | null;
private conflict: Record<string, unknown> | null;
@ -111,11 +111,9 @@ export class PublicAPI {
* Register a given source with the Ruffle Public API.
*
* @param name The name of the source.
* @param api The public API object. This must conform to the shape
* of `SourceAPI`.
*/
registerSource(name: string, api: SourceAPI): void {
this.sources[name] = api;
registerSource(name: string): void {
this.sources[name] = SourceAPI;
}
/**
@ -172,7 +170,7 @@ export class PublicAPI {
*
* @returns An instance of the Source API.
*/
newest(): SourceAPI | null {
newest(): typeof SourceAPI | null {
const name = this.newestSourceName();
return name !== null ? this.sources[name] : null;
}
@ -186,7 +184,7 @@ export class PublicAPI {
* @returns An instance of the Source API, if one or more
* sources satisfied the requirement.
*/
satisfying(ver_requirement: string): SourceAPI | null {
satisfying(ver_requirement: string): typeof SourceAPI | null {
const requirement = VersionRange.fromRequirementString(ver_requirement);
let valid = null;
@ -209,7 +207,7 @@ export class PublicAPI {
*
* @returns An instance of the Source API
*/
localCompatible(): SourceAPI | null {
localCompatible(): typeof SourceAPI | null {
if (this.sources.local !== undefined) {
return this.satisfying("^" + this.sources.local.version);
} else {
@ -223,7 +221,7 @@ export class PublicAPI {
*
* @returns An instance of the Source API
*/
local(): SourceAPI | null {
local(): typeof SourceAPI | null {
if (this.sources.local !== undefined) {
return this.satisfying("=" + this.sources.local.version);
} else {
@ -263,7 +261,6 @@ export class PublicAPI {
* version of Ruffle, since there is no Public API to upgrade from.
* @param sourceName The name of this particular
* Ruffle source.
* @param sourceAPI The Ruffle source to add.
*
* If both parameters are provided they will be used to define a new Ruffle
* source to register with the public API.
@ -271,8 +268,7 @@ export class PublicAPI {
*/
static negotiate(
prevRuffle: PublicAPI | null | Record<string, unknown>,
sourceName: string | undefined,
sourceAPI: SourceAPI | undefined
sourceName: string | undefined
): PublicAPI {
let publicAPI: PublicAPI;
if (prevRuffle instanceof PublicAPI) {
@ -281,8 +277,8 @@ export class PublicAPI {
publicAPI = new PublicAPI(prevRuffle);
}
if (sourceName !== undefined && sourceAPI !== undefined) {
publicAPI.registerSource(sourceName, sourceAPI);
if (sourceName !== undefined) {
publicAPI.registerSource(sourceName);
// Install the faux plugin detection immediately.
// This is necessary because scripts such as SWFObject check for the
@ -290,7 +286,7 @@ export class PublicAPI {
// TODO: Maybe there's a better place for this.
const polyfills = publicAPI.config.polyfills;
if (polyfills !== false) {
sourceAPI.pluginPolyfill();
SourceAPI.pluginPolyfill();
}
}

View File

@ -10,28 +10,11 @@ import { RufflePlayer } from "./ruffle-player";
* negotiator (see [[PublicAPI]]) what this particular version of Ruffle is and
* how to control it.
*/
export class SourceAPI {
private name: string;
export const SourceAPI = {
/**
* Construct a Source API.
*
* @param name The name of this particular source.
* The version of this particular API, as a string in a semver compatible format.
*/
constructor(name: string) {
this.name = name;
}
/**
* The version of this particular API.
*
* This is returned as a string in a semver compatible format.
*
* @returns The version of this Ruffle source
*/
get version(): string {
return "%VERSION_NUMBER%";
}
version: "%VERSION_NUMBER%",
/**
* Start up the polyfills.
@ -42,7 +25,7 @@ export class SourceAPI {
*/
polyfill(isExt: boolean): void {
polyfill(isExt);
}
},
/**
* Polyfill the plugin detection.
@ -51,7 +34,7 @@ export class SourceAPI {
*/
pluginPolyfill(): void {
pluginPolyfill();
}
},
/**
* Create a Ruffle player element using this particular version of Ruffle.
@ -62,5 +45,5 @@ export class SourceAPI {
createPlayer(): RufflePlayer {
const name = registerElement("ruffle-player", RufflePlayer);
return <RufflePlayer>document.createElement(name);
}
}
},
};

View File

@ -1,12 +1,8 @@
import "./index.css";
import { SourceAPI, PublicAPI } from "ruffle-core";
import { PublicAPI } from "ruffle-core";
window.RufflePlayer = PublicAPI.negotiate(
window.RufflePlayer,
"local",
new SourceAPI("local")
);
window.RufflePlayer = PublicAPI.negotiate(window.RufflePlayer, "local");
const ruffle = window.RufflePlayer.newest();
let player;

View File

@ -1,11 +1,7 @@
import * as utils from "./utils";
import { PublicAPI, SourceAPI, Letterbox } from "ruffle-core";
import { PublicAPI, Letterbox } from "ruffle-core";
const api = PublicAPI.negotiate(
window.RufflePlayer!,
"local",
new SourceAPI("local")
);
const api = PublicAPI.negotiate(window.RufflePlayer!, "local");
window.RufflePlayer = api;
const ruffle = api.newest()!;

View File

@ -1,4 +1,4 @@
import { PublicAPI, SourceAPI, Config } from "ruffle-core";
import { PublicAPI, Config } from "ruffle-core";
interface LoadMessage {
type: "load";
@ -21,8 +21,7 @@ function handleMessage(message: Message) {
};
window.RufflePlayer = PublicAPI.negotiate(
window.RufflePlayer!,
"extension",
new SourceAPI("extension")
"extension"
);
return {};
case "ping":

View File

@ -1,7 +1,3 @@
import { PublicAPI, SourceAPI } from "ruffle-core";
import { PublicAPI } from "ruffle-core";
window.RufflePlayer = PublicAPI.negotiate(
window.RufflePlayer,
"local",
new SourceAPI("local")
);
window.RufflePlayer = PublicAPI.negotiate(window.RufflePlayer, "local");