Skip to content

Commit bf09d79

Browse files
committed
Use the ESLint no-restricted-syntax rule to prevent direct usage of new Cmd()/new Name()/new Ref()
Given that all of these primitives implement caching, to avoid unnecessarily duplicating those objects *a lot* during parsing, it would thus be good to actually enforce usage of `Cmd.get()`/`Name.get()`/`Ref.get()` in the code-base. Luckily it turns out that there's an ESLint rule, which is fairly easy to use, that can be used to disallow arbitrary JavaScript syntax. Please find additional details about the ESLint rule at https://eslint.org/docs/rules/no-restricted-syntax
1 parent 3472b67 commit bf09d79

File tree

3 files changed

+32
-15
lines changed

3 files changed

+32
-15
lines changed

.eslintrc

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,6 +143,20 @@
143143
"no-multiple-empty-lines": ["error", { "max": 1, "maxEOF": 0, "maxBOF": 1, }],
144144
"no-nested-ternary": "error",
145145
"no-new-object": "error",
146+
"no-restricted-syntax": ["error",
147+
{
148+
"selector": "NewExpression[callee.name='Cmd']",
149+
"message": "Use `Cmd.get()` rather than `new Cmd()`.",
150+
},
151+
{
152+
"selector": "NewExpression[callee.name='Name']",
153+
"message": "Use `Name.get()` rather than `new Name()`.",
154+
},
155+
{
156+
"selector": "NewExpression[callee.name='Ref']",
157+
"message": "Use `Ref.get()` rather than `new Ref()`.",
158+
},
159+
],
146160
"no-unneeded-ternary": "error",
147161
"spaced-comment": ["error", "always", {
148162
"block": {

src/core/primitives.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ var Name = (function NameClosure() {
2929

3030
Name.get = function Name_get(name) {
3131
var nameValue = nameCache[name];
32+
// eslint-disable-next-line no-restricted-syntax
3233
return nameValue ? nameValue : (nameCache[name] = new Name(name));
3334
};
3435

@@ -50,6 +51,7 @@ var Cmd = (function CmdClosure() {
5051

5152
Cmd.get = function Cmd_get(cmd) {
5253
var cmdValue = cmdCache[cmd];
54+
// eslint-disable-next-line no-restricted-syntax
5355
return cmdValue ? cmdValue : (cmdCache[cmd] = new Cmd(cmd));
5456
};
5557

@@ -195,6 +197,7 @@ var Ref = (function RefClosure() {
195197
Ref.get = function(num, gen) {
196198
const key = gen === 0 ? `${num}R` : `${num}R${gen}`;
197199
const refValue = refCache[key];
200+
// eslint-disable-next-line no-restricted-syntax
198201
return refValue ? refValue : (refCache[key] = new Ref(num, gen));
199202
};
200203

test/unit/annotation_spec.js

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -461,12 +461,12 @@ describe("annotation", function() {
461461
});
462462

463463
it("should parse IRT and set default RT when not defined.", function(done) {
464-
const annotationRef = new Ref(819, 0);
464+
const annotationRef = Ref.get(819, 0);
465465
const annotationDict = new Dict();
466466
annotationDict.set("Type", Name.get("Annot"));
467467
annotationDict.set("Subtype", Name.get("Text"));
468468

469-
const replyRef = new Ref(820, 0);
469+
const replyRef = Ref.get(820, 0);
470470
const replyDict = new Dict();
471471
replyDict.set("Type", Name.get("Annot"));
472472
replyDict.set("Subtype", Name.get("Text"));
@@ -492,7 +492,7 @@ describe("annotation", function() {
492492
});
493493

494494
it("should parse IRT/RT for a group type", function(done) {
495-
const annotationRef = new Ref(819, 0);
495+
const annotationRef = Ref.get(819, 0);
496496
const annotationDict = new Dict();
497497
annotationDict.set("Type", Name.get("Annot"));
498498
annotationDict.set("Subtype", Name.get("Text"));
@@ -502,14 +502,14 @@ describe("annotation", function() {
502502
annotationDict.set("M", "D:20190423");
503503
annotationDict.set("C", [0, 0, 1]);
504504

505-
const popupRef = new Ref(820, 0);
505+
const popupRef = Ref.get(820, 0);
506506
const popupDict = new Dict();
507507
popupDict.set("Type", Name.get("Annot"));
508508
popupDict.set("Subtype", Name.get("Popup"));
509509
popupDict.set("Parent", annotationRef);
510510
annotationDict.set("Popup", popupRef);
511511

512-
const replyRef = new Ref(821, 0);
512+
const replyRef = Ref.get(821, 0);
513513
const replyDict = new Dict();
514514
replyDict.set("Type", Name.get("Annot"));
515515
replyDict.set("Subtype", Name.get("Text"));
@@ -549,7 +549,7 @@ describe("annotation", function() {
549549
});
550550

551551
it("should parse IRT/RT for a reply type", function(done) {
552-
const annotationRef = new Ref(819, 0);
552+
const annotationRef = Ref.get(819, 0);
553553
const annotationDict = new Dict();
554554
annotationDict.set("Type", Name.get("Annot"));
555555
annotationDict.set("Subtype", Name.get("Text"));
@@ -559,14 +559,14 @@ describe("annotation", function() {
559559
annotationDict.set("M", "D:20190423");
560560
annotationDict.set("C", [0, 0, 1]);
561561

562-
const popupRef = new Ref(820, 0);
562+
const popupRef = Ref.get(820, 0);
563563
const popupDict = new Dict();
564564
popupDict.set("Type", Name.get("Annot"));
565565
popupDict.set("Subtype", Name.get("Popup"));
566566
popupDict.set("Parent", annotationRef);
567567
annotationDict.set("Popup", popupRef);
568568

569-
const replyRef = new Ref(821, 0);
569+
const replyRef = Ref.get(821, 0);
570570
const replyDict = new Dict();
571571
replyDict.set("Type", Name.get("Annot"));
572572
replyDict.set("Subtype", Name.get("Text"));
@@ -608,13 +608,13 @@ describe("annotation", function() {
608608

609609
describe("TextAnnotation", function() {
610610
it("should not parse state model and state when not defined", function(done) {
611-
const annotationRef = new Ref(819, 0);
611+
const annotationRef = Ref.get(819, 0);
612612
const annotationDict = new Dict();
613613
annotationDict.set("Type", Name.get("Annot"));
614614
annotationDict.set("Subtype", Name.get("Text"));
615615
annotationDict.set("Contents", "TestText");
616616

617-
const replyRef = new Ref(820, 0);
617+
const replyRef = Ref.get(820, 0);
618618
const replyDict = new Dict();
619619
replyDict.set("Type", Name.get("Annot"));
620620
replyDict.set("Subtype", Name.get("Text"));
@@ -642,12 +642,12 @@ describe("annotation", function() {
642642
});
643643

644644
it("should correctly parse state model and state when defined", function(done) {
645-
const annotationRef = new Ref(819, 0);
645+
const annotationRef = Ref.get(819, 0);
646646
const annotationDict = new Dict();
647647
annotationDict.set("Type", Name.get("Annot"));
648648
annotationDict.set("Subtype", Name.get("Text"));
649649

650-
const replyRef = new Ref(820, 0);
650+
const replyRef = Ref.get(820, 0);
651651
const replyDict = new Dict();
652652
replyDict.set("Type", Name.get("Annot"));
653653
replyDict.set("Subtype", Name.get("Text"));
@@ -2109,7 +2109,7 @@ describe("annotation", function() {
21092109
"should correctly inherit Contents from group-master annotation " +
21102110
"if parent has ReplyType == Group",
21112111
function(done) {
2112-
const annotationRef = new Ref(819, 0);
2112+
const annotationRef = Ref.get(819, 0);
21132113
const annotationDict = new Dict();
21142114
annotationDict.set("Type", Name.get("Annot"));
21152115
annotationDict.set("Subtype", Name.get("Text"));
@@ -2118,7 +2118,7 @@ describe("annotation", function() {
21182118
annotationDict.set("M", "D:20190423");
21192119
annotationDict.set("C", [0, 0, 1]);
21202120

2121-
const replyRef = new Ref(820, 0);
2121+
const replyRef = Ref.get(820, 0);
21222122
const replyDict = new Dict();
21232123
replyDict.set("Type", Name.get("Annot"));
21242124
replyDict.set("Subtype", Name.get("Text"));
@@ -2129,7 +2129,7 @@ describe("annotation", function() {
21292129
replyDict.set("M", "D:20190523");
21302130
replyDict.set("C", [0.4]);
21312131

2132-
const popupRef = new Ref(821, 0);
2132+
const popupRef = Ref.get(821, 0);
21332133
const popupDict = new Dict();
21342134
popupDict.set("Type", Name.get("Annot"));
21352135
popupDict.set("Subtype", Name.get("Popup"));

0 commit comments

Comments
 (0)