@@ -362,58 +362,16 @@ function toJsType(field, parentIsInterface = false) {
362
362
return type ;
363
363
}
364
364
365
- function syntaxForType ( type ) {
366
-
367
- var syntax = null ;
368
- var namespace = type ;
369
-
370
- while ( syntax === null && namespace !== null ) {
371
- if ( namespace . options != null && "syntax" in namespace . options ) {
372
- syntax = namespace . options [ "syntax" ] ;
373
- }
374
- else {
375
- namespace = namespace . parent ;
376
- }
377
- }
378
-
379
- return syntax !== null ? syntax : "proto2" ;
380
- }
381
-
382
- function isExplicitPresence ( field , syntax ) {
383
-
384
- // In proto3, optional fields are explicit
385
- if ( syntax === "proto3" ) {
386
- return field . options != null && field . options [ "proto3_optional" ] === true ;
387
- }
388
-
389
- // In proto2, fields are explicitly optional if they are not part of a map, array or oneOf group
390
- if ( syntax === "proto2" ) {
391
- return field . optional && ! ( field . partOf || field . repeated || field . map ) ;
392
- }
393
-
394
- throw new Error ( "Unknown proto syntax: [" + syntax + "]" ) ;
395
- }
396
-
397
- function isImplicitPresence ( field , syntax ) {
398
-
399
- // In proto3, everything not marked optional has implicit presence (including maps and repeated fields)
400
- if ( syntax === "proto3" ) {
401
- return field . options == null || field . options [ "proto3_optional" ] !== true ;
402
- }
403
-
404
- // In proto2, nothing has implicit presence
405
- if ( syntax === "proto2" ) {
365
+ function hasPresence ( field ) {
366
+ if ( field . repeated || field . map ) {
406
367
return false ;
407
368
}
408
-
409
- throw new Error ( "Unknown proto syntax: [" + syntax + "]" ) ;
369
+ return field . partOf || // oneofs
370
+ field . declaringField || field . extensionField || // extensions
371
+ field . _features . field_presence === "EXPLICIT" ;
410
372
}
411
373
412
- function isOptionalOneOf ( oneof , syntax ) {
413
-
414
- if ( syntax === "proto2" ) {
415
- return false ;
416
- }
374
+ function isProto3Optional ( oneof ) {
417
375
418
376
if ( oneof . fieldsArray == null || oneof . fieldsArray . length !== 1 ) {
419
377
return false ;
@@ -426,8 +384,6 @@ function isOptionalOneOf(oneof, syntax) {
426
384
427
385
function buildType ( ref , type ) {
428
386
429
- var syntax = syntaxForType ( type ) ;
430
-
431
387
if ( config . comments ) {
432
388
var typeDef = [
433
389
"Properties of " + aOrAn ( type . name ) + "." ,
@@ -443,13 +399,15 @@ function buildType(ref, type) {
443
399
// With semantic nulls, only explicit optional fields and one-of members can be set to null
444
400
// Implicit fields (proto3), maps and lists can be omitted, but if specified must be non-null
445
401
// Implicit fields will take their default value when the message is constructed
446
- if ( isExplicitPresence ( field , syntax ) || field . partOf ) {
447
- jsType = jsType + "|null|undefined" ;
448
- nullable = true ;
449
- }
450
- else if ( isImplicitPresence ( field , syntax ) || field . repeated || field . map ) {
451
- jsType = jsType + "|undefined" ;
452
- nullable = true ;
402
+ if ( field . optional ) {
403
+ if ( hasPresence ( field ) ) {
404
+ jsType = jsType + "|null|undefined" ;
405
+ nullable = true ;
406
+ }
407
+ else {
408
+ jsType = jsType + "|undefined" ;
409
+ nullable = true ;
410
+ }
453
411
}
454
412
}
455
413
else {
@@ -490,7 +448,7 @@ function buildType(ref, type) {
490
448
// With semantic nulls, fields are nullable if they are explicitly optional or part of a one-of
491
449
// Maps, repeated values and fields with implicit defaults are never null after construction
492
450
// Members are never undefined, at a minimum they are initialized to null
493
- if ( isExplicitPresence ( field , syntax ) || field . partOf ) {
451
+ if ( hasPresence ( field ) && field . optional ) {
494
452
jsType = jsType + "|null" ;
495
453
}
496
454
}
@@ -514,7 +472,7 @@ function buildType(ref, type) {
514
472
// With semantic nulls, only explict optional fields and one-of members are null by default
515
473
// Otherwise use field.optional, which doesn't consider proto3, maps, repeated fields etc.
516
474
var nullDefault = config [ "null-semantics" ]
517
- ? isExplicitPresence ( field , syntax )
475
+ ? hasPresence ( field ) && field . optional
518
476
: field . optional && config [ "null-defaults" ] ;
519
477
if ( field . repeated )
520
478
push ( escapeName ( type . name ) + ".prototype" + prop + " = $util.emptyArray;" ) ; // overwritten in constructor
@@ -546,7 +504,7 @@ function buildType(ref, type) {
546
504
}
547
505
oneof . resolve ( ) ;
548
506
push ( "" ) ;
549
- if ( isOptionalOneOf ( oneof , syntax ) ) {
507
+ if ( isProto3Optional ( oneof ) ) {
550
508
push ( "// Virtual OneOf for proto3 optional field" ) ;
551
509
}
552
510
else {
0 commit comments